Retry

  1. Usage
  2. Failure Handling
  3. Max Attempts
  4. Max Duration
  5. Delays
    1. Jitter
  6. Abort
  7. Return Value
  8. Event Listeners

Retry policies are used to retry failed executions a certain number of times, with an optional delay between attempts.

Usage

Creating and using a RetryPolicy is straightforward, for example:

// Retry on ErrConnecting up to 3 times with a 1 second delay between attempts
retryPolicy := retrypolicy.Builder[Connection]().
  HandleErrors(ErrConnecting).
  WithDelay(time.Second).
  WithMaxRetries(3).
  Build()
  
// Get with retries
connection, err := failsafe.Get(Connect, retryPolicy)

Failure Handling

A RetryPolicy can be configured to handle only certain results, errors, or conditions as failures:

builder.
  HandleErrors(ErrConnecting).
  HandleResult(nil)

Max Attempts

By default, a RetryPolicy will allow a maximum of 3 execution attempts. You can configure a different max number of attempts:

builder.WithMaxAttempts(3)

Or a max number of retries:

builder.WithMaxRetries(2)

You can also disable the default max attempt limit:

builder.WithMaxAttempts(-1)

Max Duration

In addition to max attempts, you can also add a max duration for an execution, after which retries will stop if the max attempts haven’t already been reached.

builder.WithMaxDuration(5*time.Minute)

Delays

By default, a RetryPolicy has no delay between attempts. You can configure a fixed delay:

builder.WithDelay(time.Second)

Or a delay that backs off exponentially:

builder.WithBackoff(time.Second, 30*time.Second)

A random delay for some range:

builder.WithRandomDelay(time.Second, 10*time.Second)

Or a computed delay based on an execution result or error:

builder.WithDelayFunc(ComputeDelay)

Jitter

You can also combine a delay with a random jitter factor:

builder.WithJitterFactor(.1)

Or a time based jitter:

builder.WithJitter(100*time.Second)

To cancel running executions, see the execution cancellation docs or Timeout policy.

Abort

You can also specify which results, errors, or conditions to abort retries on:

builder.
  AbortOnResult(true)
  AbortOnErrors(context.Canceled)
  AbortIf(AbortCondition)

Return Value

By default, when an execution fails and a RetryPolicy is exceeded, an ExceededError will be returned, wrapping the last execution result and error:

response, err := failsafe.Get(SendMessage, retryPolicy)
var exceededErr retrypolicy.ExceededError
if errors.As(err, &exceededErr) {
  logger.Error("Failed to send message", "response", err.LastResult, "err", err.LastError)
}

A RetryPolicy can also be configured to return the last result and error instead of wrapping them:

builder.ReturnLastFailure()

If additional handling or an alternative result is needed, additional policies, such as a fallbacks, can be composed around a RetryPolicy.

Event Listeners

In addition to the standard policy event listeners, a RetryPolicy can notify you with an ExecutionEvent when a retry is scheduled or is about to be attempted, when an execution fails and the max retries are exceeded, or when retries are aborted. For example:

builder.OnRetry(func(e failsafe.ExecutionEvent[any]) {
  logger.Error("Retrying after error", "error", e.LastError())
})