I'm learning to do reactive programming with Quarkus mutiny framework. I have a 3rd party API which returns a java future, so I'm wrapping the future object into an Uni. I would like to retry incase of the failure and the below piece of code is not working as expected. I would expect the performFutureOperation
get called twice, because I have added retry, but it is getting called once.
What I am doing wrong here?
public Uni<String> nonBlockingMethod(String val) {
Future future = performFutureOperation(val);
return Uni.createFrom().future(future).onFailure().retry().atMost(1);
}
private static CompletableFuture<String> performFutureOperation(String val) {
return CompletableFuture.supplyAsync(() -> {
log.info("performFutureOperation called!");
throw new RuntimeException("test exception");
// return "processed "+val;
});
}
@Test
public void testNonBlockingMethod() {
UniAssertSubscriber<String> subscriber = nonBlockingMethod("test-id").subscribe()
.withSubscriber(UniAssertSubscriber.create());
subscriber.awaitItem().assertItem("processed test-id").assertCompleted();
}
Future objects are caching their result, so retrying on the same future object is useless. Thus, you need to make sure you re-create the future every time:
Uni<String> uni = Uni.createFrom().future(() -> performFutureOperation())
.onFailure().retry().atMost(5);
With this syntax (so passing a supplier to the future
method instead of the future directly), it recreates the future and re-executes the operation during the retries.