This tutorial shows you how to repeat the execution of a method that returns Reactor's reactive types, either Mono
or Flux
.
Please note that repeat
and repeatWhen
only work as long as the method doesn't throw error. If you want to retry execution when error occurs, you can use retry
or retryWhen
.
In this tutorial, we're going to repeat the execution of this method.
public class MyClass {
private Mono myMethod() {
System.out.println("execute myMethod");
return Mono.just("Value");
}
}
How repeat
and repeat
Work
If you apply repeat
or repeatWhen
on a method that returns Reactor's types, the method will be re-subscribed if the repeat condition fulfilled. It only executes the method once and using repeat
makes the method re-subscribed again.
The following example will not execute myMethod
when repeat occurs as it's only re-subscribed.
myClass.myMethod()
.repeat()
.blockLast()
To make myMethod
executed at every repeat, you can wrap it inside Mono.defer
.
Mono.defer(() -> myClass.myMethod())
.repeat()
.blockLast()
For method that returns Flux
, use Flux.defer
instead.
Flux.defer(() -> myClass.myFluxMethod())
.repeat()
.blockLast()
Alternatively, you can use Mono.fromSupplier
and flatten the result.
Mono.fromSupplier(myClass::myMethod).flatMap(Function.identity())
.repeat()
.blockLast()
Using repeat
Repeat Forever
If you want to repeat the the method without limit, just use .repeat()
.
Mono.fromSupplier(myClass::myMethod).flatMap(Function.identity())
.repeat()
.blockLast()
Repeat N Times
If you want to repeat it for n times, you can use .repeat(long numRepeat)
.
Mono.fromSupplier(myClass::myMethod).flatMap(Function.identity())
.repeat(10)
.blockLast()
Repeat using BooleanSupplier
If you want to use another method to determine whether it's should be repeated again or not, you can pass a BooleanSupplier
- a supplier of boolean-valued result. It works by evaluating a method that returns boolean
to determine whether it should re-subscribe. For example, you can create something like this:
private boolean shouldRepeat() {
return true;
}
Then, use it as shown on the code below
Mono.defer(() -> myClass.myMethod())
.repeat(myClass::shouldRepeat)
.blockLast()
It will repeat every time shouldRepeat
returns true.
If you want to use BooleanSupplier
as well as limiting the retry number at the same time, you can pass the limit number as first argument and the BooleanSupplier
as the second argument.
Mono.defer(() -> myClass.myMethod())
.repeat(5, myClass::shouldRepeat)
.blockLast()
In the above example, even if shouldRepeat
always returns true, the repeat will be limited at 5.
Using repeatWhen
With repeatWhen
, we can pass a function to control the repeat. For example, we can use zipWith
to limit and keep track the number of repeats and use the repeat number to create an exponential delay.
Mono.defer(() -> myClass.myMethod())
.repeatWhen(repeat -> repeat.zipWith(Flux.range(1, 5), (e, idx) -> idx)
.flatMap(time -> Mono.delay(Duration.ofSeconds(time)))
)
.blockLast()