我需要对数据流进行错误处理,以便使用相同的主键对Spanner进行多次插入。逻辑是在当前消息之后可能会收到较旧的消息,因此我不想覆盖保存的值。因此,我将创建突变作为插入,并在尝试重复插入时抛出错误。
我已经看到了DoFn中try块的几个示例,这些示例写入侧面输出以记录任何错误。这是一个非常好的解决方案,但是我需要对写入不包含DoFn的Spanner的步骤应用错误处理。
spannerBranchTuples2.get(spannerOutput2)
.apply("Create Spanner Mutation", ParDo.of(createSpannerMutation))
.apply("Write Spanner Records", SpannerIO.write()
.withInstanceId(options.getSpannerInstanceId())
.withDatabaseId(options.getSpannerDatabaseId())
.grouped());
我尚未找到任何允许将错误处理应用于此步骤的文档,或者找到了将其重新编写为DoFn的方法。有什么建议如何将错误处理应用于此吗?谢谢
答案 0 :(得分:2)
有一个有趣的pattern for this in Dataflow documentation。
基本上,我们的想法是在将结果发送到写作转换之前先准备一个DoFn
。看起来像这样:
final TupleTag<Output> successTag = new TupleTag<>() {};
final TupleTag<Input> deadLetterTag = new TupleTag<>() {};
PCollection<Input> input = /* … */;
PCollectionTuple outputTuple = input.apply(ParDo.of(new DoFn<Input, Output>() {
@Override
void processElement(ProcessContext c) {
try {
c.output(process(c.element());
} catch (Exception e) {
LOG.severe("Failed to process input {} -- adding to dead letter file",
c.element(), e);
c.sideOutput(deadLetterTag, c.element());
}
}).withOutputTags(successTag, TupleTagList.of(deadLetterTag)));
outputTuple.get(deadLetterTag)
.apply(/* Write to a file or table or anything */);
outputTuple.get(successTag)
.apply(/* Write to Spanner or any other sink */);
让我知道这是否有用!