Miltos Dimitriadis
Miltos Dimitriadis

Reputation: 91

Repeat on a Mono with Spring reactive webClient until specific response

The case is the following: There is an API endpoint that returns as response "pending" or "pompleted".

I want to repeatedly call this, let's say every 10 seconds, until I get a "Completed" response. If it keeps responding "Pending" for 5 minutes, I want a timeout.

I've read about repeat, repeatWhen and repeatWhenEmpty, but I can't get it done.

An example of my code is the following :

String getStatusResponse = webClient
            .get()
            .uri(getStatusUri)
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(String.class)
            .filter(response -> equals("completed"))
            .repeatWhenEmpty(Repeat.onlyIf(r -> false)
                    .fixedBackoff(Duration.ofSeconds(10))
                    .timeout(Duration.ofMinutes(5)))
            .block();

Edit after @Michael McFadyen's comment :

My code is now the following :

GenerationApiGetStatus getStatusResponse = webClient
        .get()
        .uri(getStatusUri)
        .accept(MediaType.APPLICATION_JSON)
        .retrieve()
        .bodyToMono(GenerationApiGetStatus.class)
        .filter(response -> response.getStatus().equals("completed"))
        .repeatWhenEmpty(Repeat.onlyIf(r -> true)
                .fixedBackoff(Duration.ofSeconds(10))
                .timeout(Duration.ofMinutes(5)))
        .block();

GenerationApiGetStatus has a property "status" for JSON unmarshalling. The problem is that I keep receiving null. If a change the code to just get once the status and go on, I correctly receive "Pending".

I believe something is wrong with the filtering :

.filter(response -> response.getStatus().equals("completed"))

Any ideas?

Upvotes: 2

Views: 2984

Answers (1)

Michael McFadyen
Michael McFadyen

Reputation: 3005

From the Api Docs of Retry.onlyIf

Repeat function that repeats only if the predicate returns true.

In your code sample you are always returning false

Repeat.onlyIf(r -> false)

As a result, the repeat will never happen.

You can alter your Retry to the code below to get your desired behaviour.

Repeat.onlyIf(r -> true)
   .fixedBackoff(Duration.ofSeconds(10))
   .timeout(Duration.ofMinutes(5))

Upvotes: 2

Related Questions