Search code examples
mutinyquarkus-reactive

Retry on failure not working with Uni.createFrom(future)


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();
}

Solution

  • 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.