Sudhanshu Gupta
Sudhanshu Gupta

Reputation: 2315

Jodah Failsafe Library Timeout is taking longer then expected

I have a situation in which I wanted to implement an API retry mechanism. Let say I have an API that calls third party API where normal response time comes under 2 seconds but sometimes we got an error saying "Service Not available", "Gateway Timeout" Etc.

So I went online to see if we have a library to handle these things and I found out https://jodah.net/failsafe/


Purpose Of using Library:-

If under 5 seconds, I don't get the result, I will cancel the execution of the current call and try one more time.

For that, In Library I can see we have timeout and retry policy.

First I am trying the timeout.

 Timeout<Object> timeout = Timeout.of(Duration.ofMillis(1000)).withCancel(true)
        .onFailure(e -> logger.error("Connection attempt timed out {} {} ",new DateTime(), e.getFailure()))
        .onSuccess(e -> logger.info("Execution completed on time"));


       try {
         logger.info("TIme: {}", new DateTime());
         result = Failsafe.with(timeout).get(() -> restTemplate.postForEntity(messageSendServiceUrl, request, String.class));

      } catch (TimeoutExceededException | HttpClientErrorException e) {
        logger.info("TIme: {}", new DateTime());
        logger.error("Timeout exception", e);

      } catch (Exception e) {
        logger.error("Exception", e);
      }

But while calculating the time I am getting 20 seconds delay between calling the API and receiving TimeoutExceededException, which should be 1 second as duration is Duration.ofMillis(1000). Below you can see a difference of 21 seconds.

TIme: 2020-06-11T10:00:17.964+05:30
Connection attempt timed out 2020-06-11T10:00:39.037+05:30 {}

Can you please let me know what I am doing wrong here.

Second is the retry policy

RetryPolicy<Object> retryPolicy = new RetryPolicy<>()
    .handle(HttpClientErrorException.class, TimeoutExceededException.class, Exception.class)
    .withDelay(Duration.ofSeconds(1))
    .withMaxRetries(3);

I want once TimeoutExceededException exception occurs after let's say 3 seconds, with a delay of 1 second, again the request is fired with max 3 retries. I am using it as

 result = Failsafe.with(retryPolicy,timeout).get(() -> restTemplate.postForEntity(messageSendServiceUrl, request, String.class));

Upvotes: 1

Views: 1771

Answers (1)

whiskeysierra
whiskeysierra

Reputation: 5120

get is a blocking or synchronous operation and it uses the calling thread. There is virtually no way for Failsafe to stop early. Timeout is best used in conjunction with an asynchronous operation, usually indicated by *Async methods. Make sure you read https://jodah.net/failsafe/schedulers/ because the default has some implications and is usually a poor choice for IO-bound operations.

Upvotes: 0

Related Questions