Description
Overview
We currently have three concrete implementations of RetryPolicy
.
MaxRetryAttemptsPolicy
MaxDurationAttemptsPolicy
PredicateRetryPolicy
Users may wish to combine certain features, such as max attempts plus a custom predicate.
However, there is no way to combine the behavior of those policies.
Furthermore, the PredicateRetryPolicy
is practically useless as a standalone policy: it does not have a way to end an infinite loop if the Retryable
continually throws an exception that matches the predicate.
In light of the above, we should replace the current built-in RetryPolicy
implementations with a fluent Builder
API and dedicated factory methods for common use cases.
In addition, we know that we will need to support "include" and "exclude" lists of exception types which a policy should honor. For example, the @Retryable
annotation will likely allow users to specify those lists declaratively.
Thus, we should also provide built-in support for specifying include/exclude lists.
Related Issues
- Revise
RetryTemplate
for alignment with Reactor (in preparation for@Retryable
) #35057 - Introduce
@Retryable
AOP support (based oncore.retry
and Reactor retry functionality) #34529
Example Usage
new MaxRetryAttemptsPolicy(5)
Gets replaced with:
RetryPolicy.withMaxAttempts(5)
new MaxDurationAttemptsPolicy(Duration.ofSeconds(5))
Gets replaced with:
RetryPolicy.withMaxDuration(Duration.ofSeconds(5))
new PredicateRetryPolicy(IOException.class::isInstance)
Gets replaced with:
RetryPolicy.builder()
.maxAttempts(3)
.predicate(IOException.class::isInstance)
.build();
The following example demonstrates all supported features of the builder.
var retryPolicy = RetryPolicy.builder()
.maxAttempts(5)
.maxDuration(Duration.ofMillis(100))
.includes(IOException.class)
.excludes(FileNotFoundException.class)
.predicate(t -> t.getMessage().contains("Unexpected failure"))
.build();