Class RetryBackoffSpec

java.lang.Object
reactor.util.retry.Retry
reactor.util.retry.RetryBackoffSpec

public final class RetryBackoffSpec extends Retry
A 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.

Author:
Simon Baslé
  • Field Details

  • Method Details

    • withRetryContext

      public RetryBackoffSpec withRetryContext(ContextView retryContext)
      Set the user provided context that can be used to manipulate state on retries.
      Parameters:
      retryContext - a new snapshot of user provided data
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • maxAttempts

      public RetryBackoffSpec maxAttempts(long maxAttempts)
      Set the maximum number of retry attempts allowed. 1 meaning "1 retry attempt": the original subscription plus an extra re-subscription in case of an error, but no more.
      Parameters:
      maxAttempts - the new retry attempt limit
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • filter

      public RetryBackoffSpec filter(Predicate<? super Throwable> errorFilter)
      Set the 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.
      Parameters:
      errorFilter - the predicate to filter which exceptions can be retried
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • modifyErrorFilter

      public RetryBackoffSpec modifyErrorFilter(Function<Predicate<Throwable>,Predicate<? super Throwable>> predicateAdjuster)
      Allows to augment a previously 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));
       
      Parameters:
      predicateAdjuster - a Function that returns a new Predicate given the currently in place Predicate (usually deriving from the old predicate).
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • doBeforeRetry

      public RetryBackoffSpec doBeforeRetry(Consumer<Retry.RetrySignal> doBeforeRetry)
      Add synchronous behavior to be executed before the retry trigger is emitted in the companion publisher. This should not be blocking, as the companion publisher might be executing in a shared thread.
      Parameters:
      doBeforeRetry - the synchronous hook to execute before retry trigger is emitted
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
      See Also:
    • doAfterRetry

      public RetryBackoffSpec doAfterRetry(Consumer<Retry.RetrySignal> doAfterRetry)
      Add synchronous behavior to be executed after the retry trigger is emitted in the companion publisher. This should not be blocking, as the companion publisher might be publishing events in a shared thread.
      Parameters:
      doAfterRetry - the synchronous hook to execute after retry trigger is started
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
      See Also:
    • doBeforeRetryAsync

      public 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.
      Parameters:
      doAsyncBeforeRetry - the asynchronous hook to execute before original retry trigger is emitted
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • doAfterRetryAsync

      public 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.
      Parameters:
      doAsyncAfterRetry - the asynchronous hook to execute after original retry trigger is emitted
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • onRetryExhaustedThrow

      public 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. 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 Retry.RetrySignal is also added as the exception's cause.
      Parameters:
      retryExhaustedGenerator - the Function that generates the Throwable for the last Retry.RetrySignal
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • transientErrors

      public RetryBackoffSpec transientErrors(boolean isTransientErrors)
      Set the transient error mode, indicating that the strategy being built should use Retry.RetrySignal.totalRetriesInARow() rather than Retry.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.

      Parameters:
      isTransientErrors - true to activate transient mode
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • minBackoff

      public RetryBackoffSpec minBackoff(Duration minBackoff)
      Set the minimum 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.
      Parameters:
      minBackoff - the minimum backoff Duration
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • maxBackoff

      public RetryBackoffSpec maxBackoff(Duration maxBackoff)
      Set a hard maximum 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).
      Parameters:
      maxBackoff - the maximum backoff Duration
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • jitter

      public RetryBackoffSpec jitter(double jitterFactor)
      Set a jitter factor for exponential backoffs that adds randomness to each backoff. This can be helpful in reducing cascading failure due to retry-storms. This method switches to an exponential backoff strategy with a zero minimum backoff if not already a backoff strategy. Defaults to 0.5 (a jitter of at most 50% of the computed delay).
      Parameters:
      jitterFactor - the new jitter factor as a double between 0d and 1d
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • multiplier

      public RetryBackoffSpec multiplier(double multiplier)
      Set a multiplier for exponential backoffs that is used as the base for each backoff. This method switches to an exponential backoff strategy with a zero minimum backoff if not already a backoff strategy. Defaults to 2.
      Parameters:
      multiplier - the new multiplier as a double
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • scheduler

      public RetryBackoffSpec scheduler(@Nullable Scheduler backoffScheduler)
      Set a 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).
      Parameters:
      backoffScheduler - the Scheduler to use, or null to revert to the default
      Returns:
      a new copy of the RetryBackoffSpec which can either be further configured or used as Retry
    • validateArguments

      protected void validateArguments()
    • generateCompanion

      public Flux<Long> generateCompanion(Flux<Retry.RetrySignal> t)
      Description copied from class: Retry
      Generates the companion publisher responsible for reacting to incoming 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.

      Specified by:
      generateCompanion in class Retry
      Parameters:
      t - the errors from the outer publisher as Retry.RetrySignal objects, containing the Throwable causing the error as well as retry counter metadata.
      Returns:
      the companion publisher responsible for reacting to incoming Retry.RetrySignal emissions, effectively deciding when to retry.