What i want to do is a conditional repeat on a Mono in Webflux with webclient.The Situation is the following:
We have some business rest service service that returns a g
Yes, it is possible.
Mono
has two concepts for re-subscribing (and thus, re-triggering the request)
Each concept has multiple overloaded methods on Mono
for different use cases. Look for the retry*
and repeat*
methods.
For example, to retry a maximum number of times with no delay, use retry(int numRetries)
.
More complex use cases are supported via the retryWhen
and repeatWhen
methods, as shown in the following examples.
To retry if the mono completed with an exception a maximum of 5 times with 5 seconds between each attempt:
// From reactor-core >= v3.3.4.RELEASE
import reactor.util.retry.Retry;
this.webClient
.post()
.uri(SERVICE_URL)
.body(BodyInserters.fromValue(docRequest))
.retrieve()
.bodyToMono(Document.class)
.retryWhen(Retry.fixedDelay(5, Duration.ofSeconds(5)))
.delaySubscription(Duration.ofSeconds(10))
The retry builder supports other backoff strategies (e.g. exponential) and other options to fully customize retries.
Note the retryWhen(Retry)
method used above was added in reactor-core v3.3.4.RELEASE, and the retryWhen(Function)
method was deprecated.
Prior to reactor-core v3.3.4.RELEASE, you could use the retry function builder from reactor-extras project to create a Function
to pass to retryWhen(Function)
.
If you need to repeat on success, then use .repeatWhen
or .repeatWhenEmpty
instead of .retryWhen
above.
Use the repeat function builder from reactor-extras project to create the repeat Function
as follows:
// From reactor-extras
import reactor.retry.Repeat;
this.webClient
.post()
.uri(SERVICE_URL)
.body(BodyInserters.fromValue(docRequest))
.retrieve()
.bodyToMono(Document.class)
.filter(document -> !document.isEmpty())
.repeatWhenEmpty(Repeat.onlyIf(repeatContext -> true)
.exponentialBackoff(Duration.ofSeconds(5), Duration.ofSeconds(10))
.timeout(Duration.ofSeconds(30)))
.delaySubscription(Duration.ofSeconds(10))
You can also chain a .retry*
with a .repeat*
if you want to re-subscribe on both success or failure.