guava-retrying

repository·master·Indexed 23 days ago

https://github.com/rholder/guava-retrying

A general-purpose Java library for retrying arbitrary code. It utilizes Guava's predicate matching for retry logic and provides advanced backoff strategies, including Exponential and Fibonacci wait patterns, via RetryerBuilder.

Tokens
1.2K
Snippets
5
Records
5
Agent score
31%

What's inside guava-retrying

  1. Install guava-retrying via Maven or Gradle

    master

    To use guava-retrying in your Java project, add the following dependency to your build configuration.

    Maven

    Add this to your pom.xml:

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

    Gradle

    Add this to your build.gradle:

    compile "com.github.rholder:guava-retrying:2.0.0"
  2. Build guava-retrying from source

    master

    The project uses Gradle. Ensure you have Git and JDK 1.6+ installed. Use ./gradlew from the root directory.

    Compile, test, and build all jars:

    ./gradlew build

    Install all jars into your local Maven cache:

    ./gradlew install
    #!/bin/bash
    ./gradlew build
    ./gradlew install
  3. Quickstart: Basic retry logic with RetryerBuilder

    master

    Use RetryerBuilder to define when to retry (based on results or exceptions) and when to stop. The Retryer then executes a Callable.

    Key behaviors:

    • retryIfResult(Predicate): Retries if the returned value matches the predicate.
    • retryIfExceptionOfType(Class): Retries if a specific exception type is thrown.
    • retryIfRuntimeException(): Retries on any RuntimeException.
    • withStopStrategy(StopStrategy): Defines the limit of retry attempts.

    Error Handling:

    • If the retry limit is reached, a RetryException is thrown.
    • If a non-specified exception occurs, it is wrapped in an ExecutionException.
    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();
    }
  4. Use Exponential Backoff for retries

    master

    Exponential backoff increases the wait time between retries exponentially. Use WaitStrategies.exponentialWait(initialDelay, maxDelay, unit) to configure this. This is useful for service polling where you want to avoid overwhelming a system.

    Example: Retry forever, increasing wait time exponentially up to a maximum of 5 minutes, then waiting 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();
  5. Use Fibonacci Backoff for retries

    master

    Fibonacci backoff uses the Fibonacci sequence to calculate increasing wait times between retries. Use WaitStrategies.fibonacciWait(initialDelay, maxDelay, unit) to configure this. This can sometimes provide better throughput than exponential backoff depending on the use case.

    Example: Retry forever, increasing wait time following the Fibonacci sequence up to a maximum of 2 minutes, then waiting 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();