Last active
March 31, 2023 06:45
-
-
Save cescoffier/e9abce907a1c3d05d70bea3dae6dc3d5 to your computer and use it in GitHub Desktop.
Various examples of retries with Mutiny
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//usr/bin/env jbang "$0" "$@" ; exit $? | |
//DEPS io.smallrye.reactive:smallrye-mutiny-vertx-web-client:1.1.0 | |
//DEPS io.smallrye.reactive:mutiny:0.7.0 | |
//DEPS org.slf4j:slf4j-nop:1.7.30 | |
package io.vertx.mutiny.retry; | |
import io.smallrye.mutiny.Uni; | |
import io.vertx.mutiny.core.Vertx; | |
import io.vertx.mutiny.ext.web.client.WebClient; | |
import java.time.Duration; | |
import java.util.Random; | |
/** | |
* Various examples of retries. | |
* CTRL+C to exist. | |
*/ | |
public class Retry { | |
public static void main(String[] args) { | |
Vertx vertx = Vertx.vertx(); | |
WebClient client = WebClient.create(vertx); | |
// Just start a picky service failing 50% of the times. | |
startPickyService(vertx); | |
System.out.println("Hit CTRL+C to exit the program"); | |
// Retrying forever | |
invokePickyService(client) | |
.onFailure().retry().indefinitely() | |
.subscribe().with(item -> System.out.println("[Retrying forever]: " + item)); | |
// Retrying at most twice | |
invokePickyService(client) | |
.onFailure().retry().atMost(2) | |
.subscribe().with( | |
item -> System.out.println("[Retrying atMost(2)]: " + item), | |
failure -> System.out.println("[Retrying atMost(2) failed]: " + failure.getMessage()) | |
); | |
// Retrying with backoff | |
invokePickyService(client) | |
.onFailure().retry().withBackOff(Duration.ofSeconds(1)).withJitter(0.2).atMost(10) | |
.subscribe().with( | |
item -> System.out.println("[Retrying backoff]: " + item), | |
failure -> System.out.println("[Retrying backoff failed]: " + failure.getMessage()) | |
); | |
// Retrying with backoff and deadline | |
invokePickyService(client) | |
.onFailure().retry().withBackOff(Duration.ofSeconds(1)).withJitter(0.2) | |
.expireIn(5000) | |
.subscribe().with( | |
item -> System.out.println("[Retrying backoff with deadline]: " + item), | |
failure -> System.out.println("[Retrying backoff with deadline]: " + failure.getMessage()) | |
); | |
} | |
private static Uni<String> invokePickyService(WebClient client) { | |
return client.getAbs("http://localhost:8080") | |
.send() | |
.onItem().transform(resp -> { | |
if (resp.statusCode() == 200) { | |
return resp.bodyAsString(); | |
} else { | |
throw new IllegalStateException(resp.bodyAsString()); | |
} | |
}); | |
} | |
private static void startPickyService(Vertx vertx) { | |
Random random = new Random(); | |
vertx.createHttpServer() | |
.requestHandler(req -> { | |
if (random.nextBoolean()) { | |
req.response().endAndForget("Hello!"); | |
} else { | |
req.response().setStatusCode(500).endAndForget("Not in a mood"); | |
} | |
}) | |
.listenAndAwait(8080); | |
} | |
} |
Hello @cescoffier,
Is it possible to retry a request and for each request, wait a certain ammount of seconds? The following code waits 30 seconds but it is considering all of the retries. What i would like to do is to wait 30 seconds for the response everytime it retries.
WebClient.create(vertx)
.get(endpoint)
.send()
.onItem()
.transformToMulti(response -> {
........................................................
return Uni.createFrom().item(response.bodyAsJsonObject().getJsonArray("content")).toMulti();
})
.onFailure()
.retry()
.withBackOff(Duration.ofSeconds(5), Duration.ofSeconds(10))
.withJitter(0.7)
.atMost(3)
.onFailure().invoke(error -> log.error("Didn't work.")
.toUni()
.await()
.atMost(Duration.ofSeconds(30));
Thank you!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In addition, i also tried to retrieve the IllegalStateException suppressed showing the number of retries attempted:
It exits from the retry block after the first iteration (http client stub is called only once in my test)