use of org.apache.gobblin.stream.ControlMessage in project incubator-gobblin by apache.
the class Converter method processStream.
/**
* Apply conversions to the input {@link RecordStreamWithMetadata}.
*/
@Override
public RecordStreamWithMetadata<DO, SO> processStream(RecordStreamWithMetadata<DI, SI> inputStream, WorkUnitState workUnitState) throws SchemaConversionException {
init(workUnitState);
this.outputGlobalMetadata = GlobalMetadata.<SI, SO>builderWithInput(inputStream.getGlobalMetadata(), Optional.fromNullable(convertSchema(inputStream.getGlobalMetadata().getSchema(), workUnitState))).build();
Flowable<StreamEntity<DO>> outputStream = inputStream.getRecordStream().flatMap(in -> {
if (in instanceof ControlMessage) {
ControlMessage out = (ControlMessage) in;
getMessageHandler().handleMessage((ControlMessage) in);
// update the output schema with the new input schema from the MetadataUpdateControlMessage
if (in instanceof MetadataUpdateControlMessage) {
this.outputGlobalMetadata = GlobalMetadata.<SI, SO>builderWithInput(((MetadataUpdateControlMessage) in).getGlobalMetadata(), Optional.fromNullable(convertSchema((SI) ((MetadataUpdateControlMessage) in).getGlobalMetadata().getSchema(), workUnitState))).build();
out = new MetadataUpdateControlMessage<SO, DO>(this.outputGlobalMetadata);
}
return Flowable.just(((ControlMessage<DO>) out));
} else if (in instanceof RecordEnvelope) {
RecordEnvelope<DI> recordEnvelope = (RecordEnvelope<DI>) in;
Iterator<DO> convertedIterable = convertRecord(this.outputGlobalMetadata.getSchema(), recordEnvelope.getRecord(), workUnitState).iterator();
if (!convertedIterable.hasNext()) {
// if the iterable is empty, ack the record, return an empty flowable
in.ack();
return Flowable.empty();
}
DO firstRecord = convertedIterable.next();
if (!convertedIterable.hasNext()) {
// if the iterable has only one element, use RecordEnvelope.withRecord, which is more efficient
return Flowable.just(recordEnvelope.withRecord(firstRecord));
} else {
// if the iterable has multiple records, use a ForkRecordBuilder
RecordEnvelope<DI>.ForkRecordBuilder<DO> forkRecordBuilder = recordEnvelope.forkRecordBuilder();
return Flowable.just(firstRecord).concatWith(Flowable.fromIterable(() -> convertedIterable)).map(forkRecordBuilder::childRecord).doOnComplete(forkRecordBuilder::close);
}
} else {
throw new UnsupportedOperationException();
}
}, 1);
outputStream = outputStream.doOnComplete(this::close);
return inputStream.withRecordStream(outputStream, this.outputGlobalMetadata);
}
use of org.apache.gobblin.stream.ControlMessage in project incubator-gobblin by apache.
the class Fork method consumeRecordStream.
@SuppressWarnings(value = "RV_RETURN_VALUE_IGNORED", justification = "We actually don't care about the return value of subscribe.")
public void consumeRecordStream(RecordStreamWithMetadata<D, S> stream) throws RecordStreamProcessor.StreamProcessingException {
if (this.converter instanceof MultiConverter) {
// if multiconverter, unpack it
for (Converter cverter : ((MultiConverter) this.converter).getConverters()) {
stream = cverter.processStream(stream, this.taskState);
}
} else {
stream = this.converter.processStream(stream, this.taskState);
}
stream = this.rowLevelPolicyChecker.processStream(stream, this.taskState);
stream = stream.mapStream(s -> s.map(r -> {
onEachRecord();
return r;
}));
stream = stream.mapStream(s -> s.doOnSubscribe(subscription -> onStart()));
stream = stream.mapStream(s -> s.doOnComplete(() -> verifyAndSetForkState(ForkState.RUNNING, ForkState.SUCCEEDED)));
stream = stream.mapStream(s -> s.doOnCancel(() -> verifyAndSetForkState(ForkState.RUNNING, ForkState.SUCCEEDED)));
stream = stream.mapStream(s -> s.doOnError(exc -> {
verifyAndSetForkState(ForkState.RUNNING, ForkState.FAILED);
this.logger.error(String.format("Fork %d of task %s failed to process data records", this.index, this.taskId), exc);
}));
stream = stream.mapStream(s -> s.doFinally(this::cleanup));
stream.getRecordStream().subscribe(r -> {
if (r instanceof RecordEnvelope) {
this.writer.get().writeEnvelope((RecordEnvelope) r);
} else if (r instanceof ControlMessage) {
this.writer.get().getMessageHandler().handleMessage((ControlMessage) r);
r.ack();
}
}, e -> logger.error("Failed to process record.", e), () -> {
if (this.writer.isPresent()) {
this.writer.get().close();
}
});
}
Aggregations