在处理错误期间,Project Reactor的助焊剂获取失败的物品

时间:2018-09-01 19:07:46

标签: java reactive-programming project-reactor

我需要处理Flux流错误,为此,我需要知道确切的项目失败了。似乎方法doOnError应该适合处理错误,但是这样我只能得到异常,而不能得到失败的项。有什么办法可以同时获取失败的项目和异常?

private void testFluxIterableFlow() {
    Flux.fromIterable(Arrays.asList(1, 2, 3, 4, 5))
            .map(this::process)
            .doOnError(ex -> {
                ...
            })
            .doOnNext(processedValue -> ...)
            .subscribe();
}

private String process(Integer value) {
    if (value == 4) {
        throw new RuntimeException("error...");
    }
    return "processed " + value;
}

在此示例中,我需要在错误处理程序中接收失败的项目4和异常消息。

2 个答案:

答案 0 :(得分:1)

如果值导致异常,则应将值视为异常原因。

由您决定是否值得添加新的异常类型,

@RequiredArgsConstructor
public class WrongValueInStreamException extends RuntimeException {
    @Getter
    private final Object wrongValue;
}

public class StreamProcessor {
    public String process(Integer value) {
        if (value == 4) {
            throw new WrongValueInStreamException(4);
        }
        return "processed " + value;
    }
}

但这是一个好习惯,只要异常传达有用的和相关的信息即可

.doOnError(WrongValueInStreamException.class::isInstance, e -> {
    final Object value = ((WrongValueInStreamException) e).getWrongValue();
    // use 'value'
})

答案 1 :(得分:0)

在这里有点晚了,但是如果有人需要它的话……可能您想做的是改用onErrorContinue。请注意,此方法将从流量中删除错误项并继续进行处理,因此请务必牢记这一点。如果您想要error + item并停止所有操作,我相信如果您重新抛出此方法的异常,并且没有其他下游onErrorContinue,它将终止通量。这是我使用kafka反应式api的示例

此外,传递给onErrorContinue的项目将不是流量中的原始项目,而是将成为在反应链中的步骤处尝试处理的对象。例如,如果在尝试转换B-> C时链失败,但在转换A-> B后,您将在处理程序中获得的对象将是B。

@EventListener(ApplicationReadyEvent.class)
public void process() {
    receiver.receiveAutoAck()
            .concatMap(Function.identity())
            .flatMap(this::deserialzeRecord)
            .flatMap(this::processEvent)
            .flatMap(responseSender::send)
            .onErrorContinue(this::handleRecordError)
            .subscribe();
}

private void handleRecordError(Throwable throwable, Object record) {
    log.error("Received error processing record={}", record, throwable);
}

如果您想终止助焊剂并放下其余项目,请这样做

private void handleRecordError(Throwable throwable, Object record) {
    log.error("Received error processing record={}", record, throwable);
    throw throwable;
}