public final class RetryBackoffSpec extends Retry
Retry
strategy based on exponential backoffs, with configurable features. Use Retry.backoff(long, Duration)
to obtain a preconfigured instance to start with.
Retry delays are randomized with a user-provided jitter(double)
factor between 0.d
(no jitter)
and 1.0
(default is 0.5
).
Even with the jitter, the effective backoff delay cannot be less than minBackoff(Duration)
nor more than maxBackoff(Duration)
. The delays and subsequent attempts are executed on the
provided backoff scheduler(Scheduler)
. Alternatively, Retry.fixedDelay(long, Duration)
provides
a strategy where the min and max backoffs are the same and jitters are deactivated.
Only errors that match the filter(Predicate)
are retried (by default all),
and the number of attempts can also limited with maxAttempts(long)
.
When the maximum attempt of retries is reached, a runtime exception is propagated downstream which
can be pinpointed with Exceptions.isRetryExhausted(Throwable)
. The cause of
the last attempt's failure is attached as said retryExhausted
exception's cause. This can be customized with onRetryExhaustedThrow(BiFunction)
.
Additionally, to help dealing with bursts of transient errors in a long-lived Flux as if each burst
had its own backoff, one can choose to set transientErrors(boolean)
to true
.
The comparison to maxAttempts(long)
will then be done with the number of subsequent attempts
that failed without an onNext
in between.
The RetryBackoffSpec
is copy-on-write and as such can be stored as a "template" and further configured
by different components without a risk of modifying the original configuration.
Retry.RetrySignal
Modifier and Type | Field and Description |
---|---|
Supplier<Scheduler> |
backoffSchedulerSupplier
|
Predicate<Throwable> |
errorFilter
The configured
Predicate to filter which exceptions to retry. |
boolean |
isTransientErrors
The configured transient error handling flag.
|
double |
jitterFactor
The configured jitter factor, as a
double . |
long |
maxAttempts
The configured maximum for retry attempts.
|
Duration |
maxBackoff
The configured maximum backoff
Duration . |
Duration |
minBackoff
The configured minimum backoff
Duration . |
Modifier and Type | Method and Description |
---|---|
RetryBackoffSpec |
doAfterRetry(Consumer<Retry.RetrySignal> doAfterRetry)
Add synchronous behavior to be executed after the retry trigger is emitted in
the companion publisher.
|
RetryBackoffSpec |
doAfterRetryAsync(Function<Retry.RetrySignal,Mono<Void>> doAsyncAfterRetry)
Add asynchronous behavior to be executed after the current retry trigger in the companion publisher,
thus delaying the resulting retry trigger with the additional
Mono . |
RetryBackoffSpec |
doBeforeRetry(Consumer<Retry.RetrySignal> doBeforeRetry)
Add synchronous behavior to be executed before the retry trigger is emitted in
the companion publisher.
|
RetryBackoffSpec |
doBeforeRetryAsync(Function<Retry.RetrySignal,Mono<Void>> doAsyncBeforeRetry)
Add asynchronous behavior to be executed before the current retry trigger in the companion publisher,
thus delaying the resulting retry trigger with the additional
Mono . |
RetryBackoffSpec |
filter(Predicate<? super Throwable> errorFilter)
Set the
Predicate that will filter which errors can be retried. |
Flux<Long> |
generateCompanion(Flux<Retry.RetrySignal> t)
Generates the companion publisher responsible for reacting to incoming
Retry.RetrySignal emissions, effectively
deciding when to retry. |
RetryBackoffSpec |
jitter(double jitterFactor)
Set a jitter factor for exponential backoffs that adds randomness to each backoff.
|
RetryBackoffSpec |
maxAttempts(long maxAttempts)
Set the maximum number of retry attempts allowed.
|
RetryBackoffSpec |
maxBackoff(Duration maxBackoff)
Set a hard maximum
Duration for exponential backoffs. |
RetryBackoffSpec |
minBackoff(Duration minBackoff)
Set the minimum
Duration for the first backoff. |
RetryBackoffSpec |
modifyErrorFilter(Function<Predicate<Throwable>,Predicate<? super Throwable>> predicateAdjuster)
|
RetryBackoffSpec |
onRetryExhaustedThrow(BiFunction<RetryBackoffSpec,Retry.RetrySignal,Throwable> retryExhaustedGenerator)
Set the generator for the
Exception to be propagated when the maximum amount of retries
is exhausted. |
RetryBackoffSpec |
scheduler(Scheduler backoffScheduler)
Set a
Scheduler on which to execute the delays computed by the exponential backoff
strategy. |
RetryBackoffSpec |
transientErrors(boolean isTransientErrors)
Set the transient error mode, indicating that the strategy being built should use
RetrySignal#totalRetriesInARow() rather than RetrySignal#totalRetries() . |
protected void |
validateArguments() |
backoff, fixedDelay, from, indefinitely, max, maxInARow, withThrowable
public final Duration minBackoff
Duration
.minBackoff(Duration)
public final Duration maxBackoff
Duration
.maxBackoff(Duration)
public final double jitterFactor
double
.jitter(double)
public final Supplier<Scheduler> backoffSchedulerSupplier
scheduler(Scheduler)
public final long maxAttempts
maxAttempts(long)
public final Predicate<Throwable> errorFilter
Predicate
to filter which exceptions to retry.filter(Predicate)
,
modifyErrorFilter(Function)
public final boolean isTransientErrors
transientErrors(boolean)
public RetryBackoffSpec maxAttempts(long maxAttempts)
maxAttempts
- the new retry attempt limitRetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec filter(Predicate<? super Throwable> errorFilter)
Predicate
that will filter which errors can be retried. Exceptions
that don't pass the predicate will be propagated downstream and terminate the retry
sequence. Defaults to allowing retries for all exceptions.errorFilter
- the predicate to filter which exceptions can be retriedRetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec modifyErrorFilter(Function<Predicate<Throwable>,Predicate<? super Throwable>> predicateAdjuster)
set
Predicate
with
a new condition to allow retries of some exception or not. This can typically be used with
Predicate.and(Predicate)
to combine existing predicate(s) with a new one.
For example:
//given
RetrySpec retryTwiceIllegalArgument = Retry.max(2)
.filter(e -> e instanceof IllegalArgumentException);
RetrySpec retryTwiceIllegalArgWithCause = retryTwiceIllegalArgument.modifyErrorFilter(old ->
old.and(e -> e.getCause() != null));
predicateAdjuster
- a Function
that returns a new Predicate
given the
currently in place Predicate
(usually deriving from the old predicate).RetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec doBeforeRetry(Consumer<Retry.RetrySignal> doBeforeRetry)
doBeforeRetry
- the synchronous hook to execute before retry trigger is emittedRetryBackoffSpec
which can either be further configured or used as Retry
andDelayRetryWith for an asynchronous version
public RetryBackoffSpec doAfterRetry(Consumer<Retry.RetrySignal> doAfterRetry)
doAfterRetry
- the synchronous hook to execute after retry trigger is startedRetryBackoffSpec
which can either be further configured or used as Retry
andRetryThen for an asynchronous version
public RetryBackoffSpec doBeforeRetryAsync(Function<Retry.RetrySignal,Mono<Void>> doAsyncBeforeRetry)
Mono
.doAsyncBeforeRetry
- the asynchronous hook to execute before original retry trigger is emittedRetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec doAfterRetryAsync(Function<Retry.RetrySignal,Mono<Void>> doAsyncAfterRetry)
Mono
.doAsyncAfterRetry
- the asynchronous hook to execute after original retry trigger is emittedRetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec onRetryExhaustedThrow(BiFunction<RetryBackoffSpec,Retry.RetrySignal,Throwable> retryExhaustedGenerator)
Exception
to be propagated when the maximum amount of retries
is exhausted. By default, throws an Exceptions.retryExhausted(String, Throwable)
with the
message reflecting the total attempt index, transient attempt index and maximum retry count.
The cause of the last RetrySignal
is also added as the exception's cause.retryExhaustedGenerator
- the Function
that generates the Throwable
for the last
RetrySignal
RetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec transientErrors(boolean isTransientErrors)
RetrySignal#totalRetriesInARow()
rather than RetrySignal#totalRetries()
.
Transient errors are errors that could occur in bursts but are then recovered from by
a retry (with one or more onNext signals) before another error occurs.
For a backoff based retry, the backoff is also computed based on the index within
the burst, meaning the next error after a recovery will be retried with a minBackoff(Duration)
delay.
isTransientErrors
- true
to activate transient modeRetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec minBackoff(Duration minBackoff)
Duration
for the first backoff. This method switches to an
exponential backoff strategy if not already done so. Defaults to Duration.ZERO
when the strategy was initially not a backoff one.minBackoff
- the minimum backoff Duration
RetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec maxBackoff(Duration maxBackoff)
Duration
for exponential backoffs. This method switches
to an exponential backoff strategy with a zero minimum backoff if not already a backoff
strategy. Defaults to Duration.ofMillis(Long.MAX_VALUE)
.maxBackoff
- the maximum backoff Duration
RetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec jitter(double jitterFactor)
0.5
(a jitter of at most 50% of the computed delay).jitterFactor
- the new jitter factor as a double
between 0d
and 1d
RetryBackoffSpec
which can either be further configured or used as Retry
public RetryBackoffSpec scheduler(@Nullable Scheduler backoffScheduler)
Scheduler
on which to execute the delays computed by the exponential backoff
strategy. Defaults to a deferred resolution of the current Schedulers.parallel()
(use
null
to reset to this default).backoffScheduler
- the Scheduler
to use, or null
to revert to the defaultRetryBackoffSpec
which can either be further configured or used as Retry
protected void validateArguments()
public Flux<Long> generateCompanion(Flux<Retry.RetrySignal> t)
Retry
Retry.RetrySignal
emissions, effectively
deciding when to retry.
When the source signals an error, that onError
signal
will be suppressed. Its Throwable
will instead be attached to a Retry.RetrySignal
, immediately emitted
on the retrySignals
publisher. Right after that emission,
request(1)
is called on the companion publisher.
The response to that request decides if a retry should be made. Thus, the outer publisher will wait until a signal is emitted by the companion publisher, making it possible to delay retry attempts.
Any
onNext
emitted by the companion publisher triggers a retry,
onError
will fail the outer publisher and
onComplete
will complete the outer publisher (effectively
suppressing the original error/Throwable
).
As an example, the simplest form of retry companion would be to return the incoming Flux
of Retry.RetrySignal
without modification. This would render a retry strategy that immediately retries, forever.
generateCompanion
in class Retry
t
- the errors from the outer publisher as Retry.RetrySignal
objects,
containing the Throwable
causing the error as well as retry counter metadata.Retry.RetrySignal
emissions,
effectively deciding when to retry.