Reputation: 49
how to use retry? i want to retry to call method when error until it`s successed. my test code
@Test
public void fun1() throws InterruptedException {
this.generate()
.retryWhen(Retry.fixedDelay(5, Duration.ofMillis(1))
.filter(e -> e instanceof Exception)
.doBeforeRetry(res -> System.out.println("retry begin"))
.doAfterRetry(res -> System.out.println("try finished")))
.onErrorContinue((throwable, o) -> System.out.println(throwable))
.subscribe(System.out::println);
}
private Mono<String> generate() throws InterruptedException {
if (retryTime.get() == 3) {
return Mono.just("Hello");
}
System.out.println("i am called" + retryTime.getAndAdd(1));
return Mono.error(new IllegalArgumentException("exception test"));
}
** but get this result**
i am called1
10:02:12.104 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
retry begin
try finished
retry begin
try finished
retry begin
try finished
retry begin
try finished
retry begin
try finished
reactor.core.Exceptions$RetryExhaustedException: Retries exhausted: 5/5
Process finished with exit code 0
why not retry three times until success???
Upvotes: 3
Views: 6774
Reputation: 4536
Retry works by re-subscribing to the result of the upstream methods. It does not re-invoke the upstream methods.
In your case specifically, each subscription from .retryWhen
is subscribing to the Mono.error
returned from the single call to generate()
. Therefore, each subscription sees the same exception result.
To fix this, you need to defer the logic inside the generate()
method to occur at subscription time, rather than assembly time.
For example, use Mono.fromCallable
, like this:
private Mono<String> generate() {
return Mono.fromCallable(() -> {
if (retryTime.get() == 3) {
return "Hello";
}
System.out.println("i am called" + retryTime.getAndAdd(1));
throw new new IllegalArgumentException("exception test");
});
}
The Callable will be called for each subscriber. Specifically, it will be called each time the retryWhen
operator re-subscribes.
Upvotes: 10