Retry
Getting started with resilience4j-retry
Create a RetryRegistry
Just like the CircuitBreaker module, this module provides an in-memory 'RetryRegistry' which you can use to manage (create and retrieve) Retry instances.
RetryRegistry retryRegistry = RetryRegistry.ofDefaults();
Create and configure Retry
You can provide a custom global RetryConfig. In order to create a custom global RetryConfig, you can use the RetryConfig builder. You can use the builder to configure:
- the maximum number of retry attempts
- the wait duration between successive attempts
- a custom Predicate which evalutas if a certain reponse should trigger a retry attempt
- a custom Predicate which evaluates if an exception should trigger a retry attempt
- a list of exceptions which should trigger a retry attempt
- a list of exceptions which should be ignored and not trigger a retry attempt
Config property | Default value | Description |
---|---|---|
maxAttempts | 3 | The maximum number of retry attempts |
waitDuration | 500 [ms] | A fixed wait duration between retry attempts |
intervalFunction | numOfAttempts -> waitDuration | A function to modify the waiting interval after a failure. By default the wait duration remains constant. |
retryOnResultPredicate | result -> false | Configures a Predicate which evaluates if a result should be retried. The Predicate must return true, if the result should be retried, otherwise it must return false. |
retryOnExceptionPredicate | throwable -> true | Configures a Predicate which evaluates if an exception should be retried. The Predicate must return true, if the exception should be retried, otherwise it must return false. |
retryExceptions | empty | Configures a list of error classes that are recorded as a failure and thus are retried. |
ignoreExceptions | empty | Configures a list of error classes that are ignored and thus are not retried. |
RetryConfig config = RetryConfig.custom()
.maxAttempts(2)
.waitDuration(Duration.ofMillis(1000))
.retryOnResult(response -> response.getStatus() == 500)
.retryOnException(e -> e instanceof WebServiceException)
.retryExceptions(IOException.class, TimeoutException.class)
.ignoreExceptions(BunsinessException.class, OtherBunsinessException.class)
.build();
// Create a RetryRegistry with a custom global configuration
RetryRegistry registry = RetryRegistry.of(config);
// Get or create a Retry from the registry -
// Retry will be backed by the default config
Retry retryWithDefaultConfig = registry.retry("name1");
// Get or create a Bulkhead from the registry,
// use a custom configuration when creating the bulkhead
RetryConfig custom = RetryConfig.custom()
.waitDuration(Duration.ofMillis(100))
.build();
Retry retryWithCustomConfig = registry.retry("name2", custom);
Decorate and execute a functional interface
As you can guess Retry has all sort of higher order decorator functions just like CircuitBreaker. You can decorate any Callable
, Supplier
, Runnable
, Consumer
, CheckedRunnable
, CheckedSupplier
, CheckedConsumer
or CompletionStage
with a Retry.
// Given I have a HelloWorldService which throws an exception
HelloWorldService helloWorldService = mock(HelloWorldService.class);
given(helloWorldService.sayHelloWorld())
.willThrow(new WebServiceException("BAM!"));
// Create a Retry with default configuration
Retry retry = Retry.ofDefaults("id");
// Decorate the invocation of the HelloWorldService
CheckedFunction0<String> retryableSupplier = Retry
.decorateCheckedSupplier(retry, helloWorldService::sayHelloWorld);
// When I invoke the function
Try<String> result = Try.of(retryableSupplier)
.recover((throwable) -> "Hello world from recovery function");
// Then the helloWorldService should be invoked 3 times
BDDMockito.then(helloWorldService).should(times(3)).sayHelloWorld();
// and the exception should be handled by the recovery function
assertThat(result.get()).isEqualTo("Hello world from recovery function");
Consume emitted RegistryEvents
You can register event consumer on a RetryRegistry and take actions whenever a Retry is created, replaced or deleted.
RetryRegistry registry = RetryRegistry.ofDefaults();
registry.getEventPublisher()
.onEntryAdded(entryAddedEvent -> {
Retry addedRetry = entryAddedEvent.getAddedEntry();
LOG.info("Retry {} added", addedRetry.getName());
})
.onEntryRemoved(entryRemovedEvent -> {
Retry removedRetry = entryRemovedEvent.getRemovedEntry();
LOG.info("Retry {} removed", removedRetry.getName());
});
Updated over 5 years ago