我正在为我的工作实现反应堆核心。如果遇到错误,我必须执行重试。以下是我添加错误之前的示例代码
FluxSink<String> mainSink;
// Create the fulx and get handle to Sink
Flux<String> mainFlux = Flux.create(sink -> {
mainSink = sink;
}, FluxSink.OverflowStrategy.BUFFER);
// Convert to Hot Flux
ConnectableFlux<String> hotFlux = mainFlux.publish();
// Two operations, add A and B to the input
hotFlux.flatMap(o -> Mono.just(o).map(s -> Mono.just(o + "A")))
.flatMap(o -> Mono.just(o).map(s -> Mono.just(o + "B")))
.log()
.subscribe();
// Activate
hotFlux.connect();
// Publish messages to test
Thread.sleep(5000);
int pendingItems = 25;
while(pendingItems > 0) {
System.out.println("Publishing " + pendingItems + " item");
mainSink.next(String.valueOf(pendingItems));
System.out.println("Published " + pendingItems + " item");
pendingItems--;
}
当我这样做时。很好。
谈到错误情况,可以说第二项操作(附加“ A”)对于项目失败。我正在尝试获得以下行为。
想知道我怎么能做到这一点。
AtomicInteger count = new AtomicInteger(0);
FluxSink<String> mainSink;
// Create the fulx and get handle to Sink
Flux<String> mainFlux = Flux.create(sink -> {
mainSink = sink;
}, FluxSink.OverflowStrategy.BUFFER);
// Convert to Hot Flux
ConnectableFlux<String> hotFlux = mainFlux.publish();
// Two operations, add A and B to the input
hotFlux.flatMap(o -> Mono.just(o).map(s -> {
System.out.println("Processing for adding A : " + o);
if(count.incrementAndGet() >= 25) {
throw new RuntimeException("More than 25th item.. Boom.. !!!");
} else {
return Mono.just(o + "A")));
}
}).retry(5)
.doOnError(throwable -> System.out.println("**** Inner Error"))
).flatMap(o -> Mono.just(o).map(s -> Mono.just(o + "B")))
.log()
.subscribe();
// Activate
hotFlux.connect();
// Publish messages to test
Thread.sleep(5000);
int pendingItems = 25;
while(pendingItems > 0) {
System.out.println("Publishing " + pendingItems + " item");
mainSink.next(String.valueOf(pendingItems));
System.out.println("Published " + pendingItems + " item");
pendingItems--;
}
当我如上所述在第一个flatMap中添加retry(5)时,它可以正常工作,它可以为第25个进入的人重试A的5次添加-从日志中可以明显看出
我无法实现完整的磁通重试(上述要求中的点(2))。我尝试在第二个通量之后添加.retry(3),以为它将重试整个通量。但这似乎没有重试。有人可以帮忙吗?
AtomicInteger count = new AtomicInteger(0);
FluxSink<String> mainSink;
// Create the fulx and get handle to Sink
Flux<String> mainFlux = Flux.create(sink -> {
mainSink = sink;
}, FluxSink.OverflowStrategy.BUFFER);
// Convert to Hot Flux
ConnectableFlux<String> hotFlux = mainFlux.publish();
// Two operations, add A and B to the input
hotFlux.flatMap(o -> Mono.just(o).map(s -> {
System.out.println("Processing for adding A : " + o);
if(count.incrementAndGet() >= 25) {
throw new RuntimeException("More than 25th item.. Boom.. !!!");
} else {
return Mono.just(o + "A")));
}
}).retry(5)
.doOnError(throwable -> System.out.println("**** Inner Error"))
).flatMap(o -> Mono.just(o).map(s -> Mono.just(o + "B")))
.retry(3)
.log()
.subscribe();
// Activate
hotFlux.connect();
// Publish messages to test
Thread.sleep(5000);
int pendingItems = 25;
while(pendingItems > 0) {
System.out.println("Publishing " + pendingItems + " item");
mainSink.next(String.valueOf(pendingItems));
System.out.println("Published " + pendingItems + " item");
pendingItems--;
}
答案 0 :(得分:0)
所有形式的retry
都通过重新订阅“重试”源来工作。冷Flux
可以解决奇迹,而热Flux
不能适应这种情况。
在这里进行publish()
转换后,无法保证以后的订阅者:由于重试被认为是后期订阅者,因此看不到任何内容,因为publish
已被原始的错误整理断开。>
您需要的是一种保留最后一项(可能导致异常的项目)并为新订阅者重播(或者为重试尝试)的方法。
另一个问题是您使用create
来获取一个FluxSink
并存储在外部,这不是一个好方法。
好消息是,使用ReplayProcessor
可以同时解决两个问题:您正确地获得了专用的接收器来手动推送数据,并且在发生错误retry
的情况下从历史记录中获取触发错误的值,然后再次尝试:
@Test
public void test() {
ReplayProcessor<String> foo =
ReplayProcessor.create(1);
FluxSink<String> sink = foo.sink();
foo.subscribe(System.out::println, System.out::println);
AtomicInteger transientError = new AtomicInteger(5);
foo.map(v -> "C".equals(v) && transientError.decrementAndGet() >= 0 ? v + (100 / 0) : v)
.doOnError(e -> System.err.println("Error, should be retried: " + e))
.retry(5)
.subscribe(System.err::println, System.err::println);
sink.next("A");
sink.next("B");
sink.next("C");
sink.complete();
}
此打印:
A
B
Error, should be retried: java.lang.ArithmeticException: / by zero
Error, should be retried: java.lang.ArithmeticException: / by zero
Error, should be retried: java.lang.ArithmeticException: / by zero
Error, should be retried: java.lang.ArithmeticException: / by zero
Error, should be retried: java.lang.ArithmeticException: / by zero
A
C
B
C