Keep Trying With Guava Retrying

written in guava, java, libs

We were having a race condition on a server which was “fixed” by adding an sleep to the thread to check again later. Yes, it sucked, so I decided to make something more sophisticated and went looking for a library to handle retries with multiple strategies. That’s when I first read about Guava Retrying.

In the words of it’s creator (rholder):

Guava-Retrying is a small extension to Google’s Guava library to allow for the creation of configurable retrying strategies for an arbitrary function call, such as something that talks to a remote service with flaky uptime.

Quick example

Let’s say we want to execute a task that will:

  • Retry if the result is null
  • Retry if an exception of type IOException is thrown
  • Wait 300 milliseconds to try again.
  • Stop after 5 attempts

Then we would do something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Callable<Boolean> yourTask = new Callable<Boolean>() {
    public Boolean call() throws Exception {
        return true; // do something interesting here
    }
};

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfResult(Predicates.<Boolean>isNull())
        .retryIfExceptionOfType(IOException.class)
        .withWaitStrategy(WaitStrategies.fixedWait(300, TimeUnit.MILLISECONDS))
        .withStopStrategy(StopStrategies.stopAfterAttempt(5))
        .build();

try {
    retryer.call(yourTask);
} catch (RetryException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

After attempting 5 times it will throw a RetryException with information about the last attempt. Any other exception thrown by your task will be wrapped and re-thrown in a ExecutionException.

Other wait strategies supported are: Random, Incremental, Exponential, Fibonacci.

Other stop strategies supported are: never stop, stop after delay.


Comments