by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Aug 03 18:10
    Tembrel commented #258
  • Aug 03 10:05
    woolamkang edited #258
  • Aug 03 10:01
    woolamkang opened #258
  • Jul 14 03:14
    timothybasanov commented #257
  • Jul 14 02:29
    jhalterman commented #257
  • Jul 14 02:27
    jhalterman commented #257
  • Jul 14 02:27
    jhalterman commented #257
  • Jul 14 02:08
    timothybasanov opened #257
  • Jul 12 18:05
    Tembrel commented #255
  • Jul 10 02:28
    gm2211 commented #255
  • Jul 09 15:25
    Tembrel commented #47
  • Jul 09 15:23
    Tembrel commented #47
  • Jul 09 10:11
    mvonrenteln commented #201
  • Jun 30 11:24
    AmarBogari edited #256
  • Jun 30 11:23
    AmarBogari opened #256
  • Jun 24 18:39
    timothybasanov commented #247
  • Jun 23 19:30
    austince commented #251
  • Jun 16 06:46
    whiskeysierra commented #255
  • Jun 16 06:18
    ke7insud opened #255
  • Jun 10 22:53
    Tembrel commented #254
Jonathan Halterman
@jhalterman
@GregJPreece There's no specific support for that type of scenario, but you could always just refresh the auth token from within your failsafe get/run method if needed:
Failsafe.with(retryPolicy).get(ctx -> {
  if (ctx.isRetry() && ctx.getLastFailure().getStatus() == 401)
    refreshAuthToken();
  doWork();
})
In general, a RetryPolicy is about deciding when to retry, but not so much about performing the retry work itself.
Greg J Preece
@GregJPreece
Thanks Jonanthan! That makes sense, I'll give it a go
Milind
@moe_twit_twitter
Hello there..I am new to Failsafe ..although I like how easy it is. Trying to implement retry scenario where I want to retry on set of exception as well as want to inspect the result for retry. Not sure but Its not working for me. Has anyone done this before? I tried to use multiple ".abortIf((T, ex) -> exceptionRetryable.apply(ex)), .abortIf((T, ex) -> resultRetryable.apply(T)) conditions or a predicate but as soon as I get result it completes the retry. Is there any example that I can look at?
Milind
@moe_twit_twitter
Jonathan Halterman
@jhalterman

@moe_twit_twitter I'm not 100% positive what your use case is, but for triggering the retry based on a result, you might want to use the handleIf or handleResult methods.

https://jodah.net/failsafe/javadoc/net/jodah/failsafe/FailurePolicy.html#handleIf-java.util.function.BiPredicate-
https://jodah.net/failsafe/javadoc/net/jodah/failsafe/FailurePolicy.html#handleResult-R-

Stavros Demarchos
@stsdema28_twitter

Hello there,
I started using Failsafe and I have a question regarding retryPolicy.

Basically I defined a simple retry policy with back off and I specify a particular RuntimeException (e.g IllegalArgumentException) with the handle method.
For some reason, it retries on all RuntimeExceptions, not only in the case of the one I provide.

If I specify the same exception with abortOn method, it does skip it so the predicate works.
Here: https://jodah.net/failsafe/policies/
It is mentioned that by default it handles any Exception by we can be specific with handle methods.
What's the best way to retry only on specific RuntimeExceptions?
I am using the latest version 2.3.3.

Willi Schönborn
@whiskeysierra
@stsdema28_twitter Can you paste a minimal code block here that highlights your issue?
Stavros Demarchos
@stsdema28_twitter
fun doSomething(): () -> Nothing = {
    throw NullPointerException()
}

fun main() {

    val policy = RetryPolicy<Any>()
        .handle(IllegalArgumentException::class.java)
        .handleResult(null)
        .withBackoff(1,2, ChronoUnit.MILLIS)
        .withMaxRetries(2)
        .onRetry { println("Boom") }

    try {
        Failsafe.with(policy).get(doSomething())
    }
    catch (e: NullPointerException) {
        println(e)
    }
}
I think I found the issue.
If we remove .handleResult(null), the retry logic works fine. It does not retry due to NullPointerException. But, as it is atm, for some reason it retries.
I wanted to have a policy to retry on particular exception and when the result is null.
Jonathan Halterman
@jhalterman
The policy above will definitely not retry on all RuntimeExceptions, only on IllegalArgumentException OR null. If you're able to reproduce something different, please file an issue with a reproducer.
Stavros Demarchos
@stsdema28_twitter

the above code prints:

Boom
Boom
java.lang.NullPointerException

If we remove .handleResult(null), it prints only

java.lang.NullPointerException
It shouldnt retry on NullPointerException, I will raise an issue.
Stavros Demarchos
@stsdema28_twitter
@jhalterman I created the issue jhalterman/failsafe#240
Jonathan Halterman
@jhalterman
@stsdema28_twitter Thanks for reporting this :thumbsup:
Jonathan Halterman
@jhalterman
tgomes
@tuliogomesbarbosa
Hey @jhalterman, wasn't this snippet suppose to work out of the box?
Failsafe.with(Timeout.of(Duration.ofSeconds(5))).get(() ->
I've put a onFailure and nothing is being thrown, and I'm quite sure it should throw because the target system is down.
Let me know if a should open an issue. Version 2.3.4.
Jonathan Halterman
@jhalterman
@tuliogomesbarbosa By default, Timeout will cause an execution to fail with TimeoutExceededException. That exception should be thrown (and is a bug if it's not) when the execution completes. If you want to interrupt the execution before it completes, set .withCancel(true).
thoec
@thoec

Hi,

I use failsafe and are having trouble with getting delay and backoff strategy to work. Besides the missing delay it works fine. I am using failsafe 2.3.4.

Using .withDelay or .withBackoff in my RetryPolicy results in retries with no delay. Other settings, such as maxRetries and handleResultIf are respected. Is there anything obvious that I'm doing wrong?

My code:

RetryPolicy<HttpResponse> retryPolicy = new RetryPolicy<HttpResponse>()
.handleResultIf(r -> r == null || (r.getStatusLine()
.getStatusCode() < 200 || r.getStatusLine()
.getStatusCode() >= 300))
.withBackoff(100, 60000, ChronoUnit.MILLIS)
.withMaxAttempts(5);

return Failsafe.with(retryPolicy)
.getStageAsync(() -> CompletableFuture.supplyAsync(() -> {...

Thanks

Jonathan Halterman
@jhalterman
@thoec I'm wondering if the problem is somehow related to using getStageAsync, because otherwise using withBackoff is pretty common. Do you have a more complete example of using getStageAsync that fails to delay?
thoec
@thoec
@jhalterman excuse me, the code I posted is not what causing the problem, sorry for the confusion. I see the problem with this code:
private String fail() { return "failed"; }

@Test
void runFailedTest() throws ExecutionException, InterruptedException {
  CompletableFuture<String> resultFuture = new CompletableFuture<>();

  RetryPolicy<String> retryPolicy = new RetryPolicy<String>()
    .handleResultIf(r -> r == null || (r.equals("failed")))
    .withBackoff(100, 60000, ChronoUnit.MILLIS)
    .withMaxAttempts(10)
    .onRetry(e -> log.info("Retrying:{}", e))
    .onFailedAttempt(e -> log.error(String.format("Failed attempt for: %s", e), e));

  Failsafe.with(retryPolicy)
    .onFailure(e -> log.error(String.format("Failed to call: %s", e), e))
    .onSuccess(e -> log.info("Call done: {}", e))
    .runAsyncExecution(execution -> {
      String k = fail();
      if (execution.complete(k)) {
        resultFuture.complete(k);
      } else if (!execution.retry()) {
        log.info("Giving up");
      } else {
        log.info("retry scheduled");
      }
    });

    log.info("Res: {}", resultFuture.get());
}
thoec
@thoec
Another question, there is an example for integrating with Netty on the Failsafe website at https://jodah.net/failsafe/example-integrations/. Is there any example for integrating with Java NIO directly? I use org.apache.http.impl.nio.client and it would be really nice to handle retries without creating threads for each call, and instead let the org.apache.http.impl.nio.reactor run the retries asynchronously as part of its event loop.
Jonathan Halterman
@jhalterman
@thoec Answering your last question first, there's no example for NIO, but if you're up for adding one via a PR, that would be great.
Jonathan Halterman
@jhalterman
@thoec Re: runAsyncExecution not respecting delays, this appears to be a bug. I opend jhalterman/failsafe#242
This appears to be specific to async executions. Will fix soon.
Jonathan Halterman
@jhalterman
@thoec This is fixed in master. Thanks for reporting.
thoec
@thoec
@jhalterman thanks :smiley: I will keep the NIO example PR in mind
thoec
@thoec
And another question. In my unit tests I depend on the onComplete-listener. Looking at the Failsafe code I can see that that listener is called after the future from Failsafe is completed (which makes my tests flaky, since they wait for the future to complete...). Shouldn't any calls to listeners in FailsafeFuture::completeResult be done before completing the future?
Jonathan Halterman
@jhalterman
@thoec It's debatable what the right thing to do is with the ordering of completing the future and calling the listeners. The reason I chose to complete the future first then call the listeners is because that's what CompletableFuture does, FWIW, and I wanted Failsafe's listeners to behave similar to that.
thoec
@thoec
@jhalterman I understand, thanks. No problem really, there are easy remedies for the problems I had once you understand what the call sequence looks like.
Jonathan Halterman
@jhalterman
Just pushed out 2.3.5, which includes a minor bugfix.
Diego Molina
@diemol
Hi all, I am aware that the RetryPolicy objective is to retry when there are failures, but...
is someone using a RetryPolicy just to keep some code running with a given delay and backoff?
Jonathan Halterman
@jhalterman
That might be uncommon, but sounds like a fine use case
Diego Molina
@diemol
but still, I do need to declare or provoke some failure in order to have the RetryPolicy kick in, right?
Jonathan Halterman
@jhalterman
Failsafe is oriented around handling failures, but you can specify what represents a failure. And it can be anything. For example, if you want every result to be handled as a failure: retryPolicy.handleResultIf(result -> true)
RetryPolicy extends FailurePolicy and has a few options for specifying when to handle some execution result:`https://jodah.net/failsafe/javadoc/net/jodah/failsafe/FailurePolicy.html
Diego Molina
@diemol
makes sense, I didn't see it from that point of view
thank you @jhalterman
thierryb180381
@thierryb180381

Hello,

I would like to use FailSafe to do something like that:

```
   String error = null;
    ResponseType response = null;
    int count = 0;
    int maxTries = 1;
    while (count < maxTries + 1) {
        try {
            response = myService.call(request);
            doSomethingMore()
            break;
        } catch (Exception e) {
            error = e.getMessage();
            TimeUnit.SECONDS.sleep(1);
            count++;
        }
    }
```

it's important for me to catch Exception, to not have a big stack strace in my logs. So after those calls if error, the exception message will be in my variable error and could be exploited further to build my response that will contain an error message taken from exception.

If I do something like that (certainly a bad use):

                ResponseType  response = Failsafe
                .with(retryPolicy)
                // appel mock pour sauvegarde des pdfs
                .onSuccess(e -> doSomethingMore()))
                .onFailure(e -> {
                    logger.error("Failed... : {}", e.getFailure().getMessage());
                })
                .get(() -> myService.call(request));

I have a big stracktrace in ly logs as Exception is not catched.

How could I do that?

Thank you.

Willi Schönborn
@whiskeysierra
So in case you have at least one retry (caused by at least one exception) you want to have both the error and response variable bet set and inspect both to create your result?
thierryb180381
@thierryb180381

Hello,

For example, it makes a first call :

  • if it succeeds, it's ok. I will use the response to build my final response
  • if it fails (because of any exception), then catch Exception, because I don't want a big stack trace, and retries according to maxTries.
    At the end, if it's always failed, be able to retrieve the last exception error in variable error, and use it to build my final response that will contain that error message.

I hope, it's more clear.

Thank you.

Jonathan Halterman
@jhalterman
@thierryb180381 If you want to catch an exception and replace it with something else, or suppress it, you can use a fallback outside of your retry policy. This is not much different than using a catch block, but something like:
Fallback<String> fallback = Fallback.of(e -> {
  // Build and return an error string when the execution fails
  return buildResponse(e.getLastFailure().toString());
});

Failsafe.with(fallback, retryPolicy).get(() -> myService.call(request));
thierryb180381
@thierryb180381
Hello @jhalterman , thank you for your answer, it works perfectly :).
Jonathan Halterman
@jhalterman

Time based circuit breakers have been merged to master and are set to be released. If you want to have a look and request any changes before the release, now is the time :)

The commit is: jhalterman/failsafe@c4ce4a0
The commit for the website docs is: jhalterman/failsafe@fc53532

Jonathan Halterman
@jhalterman
Failsafe 2.4.0 was released, which includes time based circuit breakers: https://jodah.net/failsafe/circuit-breaker/#configuration
Clifton T. Mtengezo
@tikomtengezo_twitter

I have a situation:

  1. When I send an http request e.g. makePayment, I can get
    a. Success e,g, http status 200
    b. Failure e.g. http status other than 200
    c. Exception e.g. Connect Timeout, GateWay Timeout

  2. When I get a success or a filure, I will work with it and return to the client

  3. When I get an exception, mainly Gateway Timeout exception, I do NOT want to return it. I do NOT want to repeat the original request (makePayment), I want to send a completely new request e.g. confirmPayment to a different end point.

  4. So the result of the makePayment request can either be response obtained after first attempt if it was successful or response obtained from repeatedly (3 times) sending confirmPayment request.

How can I achieve this with Failsafe?
My apologies I am new to Failsafe. If this question was already asked, direct me to the answer.

Thank you in advance.

Jon Harkness
@ness2u
I found a bug in some library, that happens to use Failsafe for retries. I'm trying to update that library, by continuing to use Failsafe for retries, but making it proper non-blocking/async...
The only formal sample I see is https://jodah.net/failsafe/async-api/ but it isn't complete... is there a better sample, including the policy, to handle proper async retries?
Jonathan Halterman
@jhalterman

@ness2u That example is lacking a better explanation, but basically since we're async, you need to manually indicate when you want to schedule a retry via one of the retry methods. You an also, optionally, attempt to complete the execution (and the associated future) via the complete methods. The retry methods that take arguments will do both - attempt to complete the execution, else retry. https://jodah.net/failsafe/javadoc/net/jodah/failsafe/AsyncExecution

Most of the complete/retry methods return boolean, which indicates whether the execution could be completed or whether a retry was successfully scheduled, both of which are based on the RetryPolicy.

5 replies
Jonathan Halterman
@jhalterman

@tikomtengezo_twitter The most common way to change a request for a retry is something like this:

    RetryPolicy<HttpResponse> retryPolicy = new RetryPolicy<HttpResponse>().withMaxAttempts(4).handle(GatewayTimeoutException.class);
    Failsafe.with(retryPolicy).get(ctx -> {
      if (ctx.isFirstAttempt())
        makePayment();
      else
        confirmPayment();
    });

This might not be perfect if GatewayTimeoutException only occurs when calling makePayment and the failure is something else when calling confirmPayment, but you could probably tweak the RetryPolicy to deal with this.

Another option is to use two Failsafe calls, the first one with a Fallback which makes the second request using retries. Ex:

    Fallback<HttpResponse> fallback = Fallback.of(e -> {
      RetryPolicy<HttpResponse> retryPolicy = new RetryPolicy<HttpResponse>().withMaxAttempts(3);
      Failsafe.with(retryPolicy).get(() -> confirmPayment);
    }).handle(GatewayTimeoutException.class);
    Failsafe.with(fallback).get(() -> makePayment());