Open pendula95 opened 1 year ago
retry means using a function, at the same time we do have a circuit breaker in vertx that is somehow related to that, so it would be good to think about a generic mechanism that makes this, perhaps in circuit breaker
Ok let my try to explain what I am trying to do via code usecase. I see that there is a similar functionality via circuit breaker but it looks like an feature that is designed for microservice management and architecture. What I want simply is to retry a future when specific conditions are meet. I don't like an idea of importing a microservice manager like circuit breaker in order to get simple functionality.
Lets say I have simple HttpClient that uses keep alive with a server. Pool is made an maintained. Lets say for some unknown reason server process restarts unexpectedly. In this case depending on the pool size my x requests will fail because all connections are dead but this does not mean I can not deliver my HTTP call. In order to avoid this with vert.x core I would need to write something like this:
public static Future<HttpResponse<Buffer>> sendRequestWithRetry(int retryCount) {
Promise<HttpResponse<Buffer>> promise = Promise.promise();
webClient.getAbs("http://localhost:9999")
.send()
.onSuccess(promise::complete)
.onFailure(ex -> {
if (ex.getMessage() != null && ex.getMessage().contains("Connection reset by peer") && retryCount < 3) {
sendRequestWithRetry(retryCount + 1)
.onSuccess(promise::complete)
.onFailure(promise::fail);
} else {
promise.fail(ex);
}
});
return promise.future();
}
So anywhere in the code I need to retry I would need to write helper retry functions like this. Also good usecase is with redis connector where I would like to retry a future if the response is empty (date still did not make it) and I would like to retry 3 times with delay of 300 ms as data might be late and I want to get it.
So in my opinion this should be migrate to Future API and then circuit breaker can wrap it in its own API as it currently does.
A future is a (deferred) value. You cannot retry a value.
What you can retry is an operation which is lazily defined. That is possible in two ways with Vert.x:
integration with a reactive programming library: Mutiny, RxJava Both libs provide methods to inspect the operation failure and retry if necessary
using the Vert.x Circuit breaker Provides operation failure inspection and configuration delays for retrying
Le ven. 10 mars 2023 à 16:25, Lazar Bulić @.***> a écrit :
Ok let my try to explain what I am trying to do via code usecase. I see that there is a similar functionality via circuit breaker but it looks like an feature that is designed for microservice management and architecture. What I want simply is to retry a future when specific conditions are meet. I don't like an idea of importing a microservice manager like circuit breaker in order to get simple functionality.
Lets say I have simple HttpClient that uses keep alive with a server. Pool is made an maintained. Lets say for some unknown reason server process restarts unexpectedly. In this case depending on the pool size my x requests will fail because all connections are dead but this does not mean I can not deliver my HTTP call. In order to avoid this with vert.x core I would need to write something like this:
public static Future<HttpResponse
> sendRequestWithRetry(int retryCount) { Promise<HttpResponse > promise = Promise.promise(); webClient.getAbs("http://localhost:9999") .send() .onSuccess(promise::complete) .onFailure(ex -> { if (ex.getMessage() != null && ex.getMessage().contains("Connection reset by peer") && retryCount < 3) { sendRequestWithRetry(retryCount + 1) .onSuccess(promise::complete) .onFailure(promise::fail); } else { promise.fail(ex); } }); return promise.future(); } So anywhere in the code I need to retry I would need to write helper retry functions like this. Also good usecase is with redis connector where I would like to retry a future if the response is empty (date still did not make it) and I would like to retry 3 times with delay of 300 ms as data might be late and I want to get it.
So in my opinion this should be migrate to Future API and then circuit breaker can wrap it in its own API as it currently does.
— Reply to this email directly, view it on GitHub https://github.com/eclipse-vertx/vert.x/issues/4619#issuecomment-1463963240, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALOLNVEQAXWCJJDZSYJG3TW3NBXBANCNFSM6AAAAAAVDHR7KI . You are receiving this because you are subscribed to this thread.Message ID: @.***>
This looks like what you need
It's not as elegant/dynamic, just another means to model it. I think it should work(?):
public static Future<HttpResponse<Buffer>> sendRequestWithRetry(int retryCount) {
return sendRequest()
.recover(retry())
.recover(retry())
.recover(retry());
}
private static Function<Throwable, Future<HttpResponse<Buffer>>> retry() {
return ex -> {
if (Objects.requireNonNullElse(ex.getMessage(), "").contains("Connection reset by peer")) {
return sendRequest();
} else {
return Future.failedFuture(ex);
}
};
}
private static Future<HttpResponse<Buffer>> sendRequest() {
return webClient.getAbs("http://localhost:9999").send();
}
Introduce configurable retry mechanism on Future interface.
There are many use causes where this feature would be useful and would shorten a lot of boilerplate code that is copied and reused on many places in user code. Example is, retry of WebClient HTTP request that fails for recoverable reasons.
This is already available on rx api via multiple functions:
I would suggest to add support for 3,4,5 as in my opinion they seam as the most common and useful ones.
I would be willing to contribute this solution. This can be a nice addition to vertx5 API