Retry
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())
})