• Stars
    star
    1,427
  • Rank 32,734 (Top 0.7 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created about 12 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

This 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.

Build Status Latest Version License

##What is this? The guava-retrying module provides a general purpose method for retrying arbitrary Java code with specific stop, retry, and exception handling capabilities that are enhanced by Guava's predicate matching.

This is a fork of the excellent RetryerBuilder code posted here by Jean-Baptiste Nizet (JB). I've added a Gradle build for pushing it up to my little corner of Maven Central so that others can easily pull it into their existing projects with minimal effort. It also includes exponential and Fibonacci backoff WaitStrategies that might be useful for situations where more well-behaved service polling is preferred.

##Maven

    <dependency>
      <groupId>com.github.rholder</groupId>
      <artifactId>guava-retrying</artifactId>
      <version>2.0.0</version>
    </dependency>

##Gradle

    compile "com.github.rholder:guava-retrying:2.0.0"

##Quickstart A minimal sample of some of the functionality would look like:

Callable<Boolean> callable = new Callable<Boolean>() {
    public Boolean call() throws Exception {
        return true; // do something useful here
    }
};

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfResult(Predicates.<Boolean>isNull())
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withStopStrategy(StopStrategies.stopAfterAttempt(3))
        .build();
try {
    retryer.call(callable);
} catch (RetryException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

This will retry whenever the result of the Callable is null, if an IOException is thrown, or if any other RuntimeException is thrown from the call() method. It will stop after attempting to retry 3 times and throw a RetryException that contains information about the last failed attempt. If any other Exception pops out of the call() method it's wrapped and rethrown in an ExecutionException.

##Exponential Backoff

Create a Retryer that retries forever, waiting after every failed retry in increasing exponential backoff intervals until at most 5 minutes. After 5 minutes, retry from then on in 5 minute intervals.

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.MINUTES))
        .withStopStrategy(StopStrategies.neverStop())
        .build();

You can read more about exponential backoff and the historic role it played in the development of TCP/IP in Congestion Avoidance and Control.

##Fibonacci Backoff

Create a Retryer that retries forever, waiting after every failed retry in increasing Fibonacci backoff intervals until at most 2 minutes. After 2 minutes, retry from then on in 2 minute intervals.

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfExceptionOfType(IOException.class)
        .retryIfRuntimeException()
        .withWaitStrategy(WaitStrategies.fibonacciWait(100, 2, TimeUnit.MINUTES))
        .withStopStrategy(StopStrategies.neverStop())
        .build();

Similar to the ExponentialWaitStrategy, the FibonacciWaitStrategy follows a pattern of waiting an increasing amount of time after each failed attempt.

Instead of an exponential function it's (obviously) using a Fibonacci sequence to calculate the wait time.

Depending on the problem at hand, the FibonacciWaitStrategy might perform better and lead to better throughput than the ExponentialWaitStrategy - at least according to A Performance Comparison of Different Backoff Algorithms under Different Rebroadcast Probabilities for MANETs.

The implementation of FibonacciWaitStrategy is using an iterative version of the Fibonacci because a (naive) recursive version will lead to a StackOverflowError at a certain point (although very unlikely with useful parameters for retrying).

Inspiration for this implementation came from Efficient retry/backoff mechanisms.

##Documentation Javadoc can be found here.

##Building from source The guava-retrying module uses a Gradle-based build system. In the instructions below, ./gradlew is invoked from the root of the source tree and serves as a cross-platform, self-contained bootstrap mechanism for the build. The only prerequisites are Git and JDK 1.6+.

check out sources

git clone git://github.com/rholder/guava-retrying.git

compile and test, build all jars

./gradlew build

install all jars into your local Maven cache

./gradlew install

##License The guava-retrying module is released under version 2.0 of the Apache License.

##Contributors

  • Jean-Baptiste Nizet (JB)
  • Jason Dunkelberger (dirkraft)
  • Diwaker Gupta (diwakergupta)
  • Jochen Schalanda (joschi)
  • Shajahan Palayil (shasts)
  • Olivier Grégoire (fror)
  • Andrei Savu (andreisavu)
  • (tchdp)
  • (squalloser)
  • Yaroslav Matveychuk (yaroslavm)
  • Stephan Schroevers (Stephan202)
  • Chad (voiceinsideyou)
  • Kevin Conaway (kevinconaway)
  • Alberto Scotto (alb-i986)

More Repositories

1

retrying

Retrying is an Apache 2.0 licensed general-purpose retrying library, written in Python, to simplify the task of adding retry behavior to just about anything.
Python
1,910
star
2

gradle-one-jar

The gradle-one-jar project is a Gradle plugin that uses One-JAR, a specialised Class-Loader written by Simon Tuffs (http://one-jar.sourceforge.net/), for building self-contained executable jars that include all dependencies.
Groovy
218
star
3

gradle-view

The Gradle View IntelliJ IDEA plugin shows a split tree rollup of the dependencies for each Gradle configuration in use by a project.
Java
179
star
4

csv2es

Load a CSV (or TSV) file into an Elasticsearch instance
Python
62
star
5

fauxflake

Fauxflake is an easily embeddable, decentralized, k-ordered unique ID generator.
Java
41
star
6

snowball-stemmer

This is a repackaging of a version of the snowball-stemmer found at http://snowball.tartarus.org/ so that it's available on Maven Central.
Java
19
star
7

nilsimsa

This module contains an implementation of the Nilsimsa locality-sensitive hashing algorithm in Java.
Java
18
star
8

debinate

Roll up your projects into little standalone Debian packages.
Shell
14
star
9

gradle-autojar

The gradle-autojar project is a Gradle plugin that uses Autojar, a specialized jar archive minimizer written by Bernd Eggink (http://autojar.sourceforge.net/), for building self-contained executable jars that include only those dependencies that are actually used.
Groovy
14
star
10

esthree

An S3 client that just works
Java
8
star
11

i3status-title-on-bar

Inject the active window title into the output of i3status.
Go
8
star
12

sshuttle-binary

This is a single-binary package of sshuttle.
Python
7
star
13

jvm-loop-unswitching-bug

Cause the JVM to produce a segmentation fault from org.apache.http.impl.cookie.BestMatchSpec.formatCookies
Java
7
star
14

dynq

Dynq is a DynamoDB client intended to make querying and sourcing environment variables from the commandline very easy.
Python
6
star
15

jfpm

Run fpm (which lets you build RPM's, DEB's, etc.) from a single standalone binary using the JVM.
Shell
6
star
16

grepby

Output counts of matching regular expressions like a group by for grep.
Go
5
star
17

gradle-wrapper-here

Drop a Gradle wrapper in the current directory.
Shell
4
star
18

moar-concurrent

This module contains a collection of useful builders and concurrency classes to assist in modeling complex or overly tweakable concurrent processing pipelines.
Java
4
star
19

oggtrackutil

This is a simple audio extraction utility written during a weekend to extract well-formed, single track WAV files from any compressed Ogg Vorbis audio file including those with more than 8 tracks.
C
3
star
20

ns4600

This is a small Python module to control the Promise SmartStor NS4600 NAS server.
Python
2
star
21

jfss

Run fss, which lets you provision cloud infrastructure Chef-style with only shell scripts, from a single standalone binary using the JVM.
Java
1
star
22

laptop-sleep-tool

Tinker with sleep mode settings on your laptop with this little tool.
Shell
1
star
23

python-debian-packaging

This is a collection of slides, etc. for my Python and Debian packaging talk.
JavaScript
1
star
24

windowtools

This is a collection of scripts for manipulating windows on various Linux desktop environments.
Shell
1
star
25

rholder.github.com

JavaScript
1
star
26

cram-maven-plugin

1
star
27

transaction-binding

This project extracts some of the transactional binding functionality from Alfresco 3.2's core libraries, and it aims to rely on very minimal external runtime dependencies.
Java
1
star
28

uci-security

UCI Security is a derivative of RBAC that slightly rearranges the components found in a traditional access control system. It includes the familiar idea of roles to the extent that they are used to control the access a particular user has within the system, but also introduces a new way of thinking about how their relationship to a particular situation is relevant.
1
star