Normandy.Resilience.Retry
(normandy v2.2.0)
View Source
Retry mechanism with exponential backoff for handling transient failures.
Provides configurable retry logic for operations that may fail temporarily, such as network requests, API calls, or resource access.
Features
- Exponential backoff with jitter
- Configurable retry limits
- Custom retry conditions
- Detailed error tracking
Example
# Basic retry with defaults
Retry.with_retry(fn ->
MyAPI.call()
end)
# Custom retry configuration
Retry.with_retry(
fn -> MyAPI.call() end,
max_attempts: 5,
base_delay: 1000,
max_delay: 30_000,
retry_on: [:network_error, :rate_limit]
)
# With custom retry condition
Retry.with_retry(
fn -> MyAPI.call() end,
retry_if: fn error ->
match?({:error, :temporary}, error)
end
)
Summary
Functions
Create a retry configuration for common scenarios.
Checks retry options without running anything, raising ArgumentError on an
unknown option or a bad value. BaseAgent.init/1 calls it for
:retry, so a mistake surfaces when the agent is built.
Execute a function with retry logic.
Types
@type retry_option() :: {:max_attempts, pos_integer()} | {:base_delay, pos_integer()} | {:max_delay, pos_integer()} | {:backoff_factor, float()} | {:jitter, boolean()} | {:retry_on, [atom()]} | {:retry_if, (term() -> boolean())}
@type retry_options() :: [retry_option()] | %{optional(atom()) => term()}
Functions
@spec preset(atom()) :: [retry_option()]
Create a retry configuration for common scenarios.
Presets
:quick- Fast retries for quick operations (2 attempts, 100ms base):standard- Balanced configuration (3 attempts, 1s base):persistent- More aggressive retries (5 attempts, 1s base):patient- Long-running retries (10 attempts, 2s base)
Examples
Retry.with_retry(fn -> api_call() end, Retry.preset(:persistent))
@spec validate_options!(retry_options()) :: :ok
Checks retry options without running anything, raising ArgumentError on an
unknown option or a bad value. BaseAgent.init/1 calls it for
:retry, so a mistake surfaces when the agent is built.
@spec with_retry(function(), retry_options()) :: {:ok, term()} | {:error, {term(), pos_integer(), [term()]}}
Execute a function with retry logic.
Options
:max_attempts- Maximum number of attempts (default: 3):base_delay- Initial delay in milliseconds (default: 1000ms):max_delay- Maximum delay in milliseconds (default: 32000ms):backoff_factor- Exponential backoff multiplier (default: 2.0):jitter- Add randomness to delays (default: true):retry_on- List of error types to retry on (default: network errors, timeouts, rate limits):retry_if- Custom retry condition function
Options are a keyword list or a map. An unknown or repeated option or a bad value raises
ArgumentError.
Returns
{:ok, result}- Success after 1 or more attempts{:error, {reason, attempts, errors}}- every failure:reasonis the last error,attemptshow many were made (1 for a non-retryable error), anderrorsall of them in order. A return that is neither{:ok, _}nor{:error, _}is the error{:unexpected_return, value}.
Examples
# Retry with defaults
{:ok, result} = Retry.with_retry(fn ->
{:ok, perform_operation()}
end)
# Custom configuration
{:ok, result} = Retry.with_retry(
fn -> risky_operation() end,
max_attempts: 5,
base_delay: 500
)
# Custom retry condition
Retry.with_retry(
fn -> custom_call() end,
retry_if: fn
{:error, %{status: status}} when status >= 500 -> true
_ -> false
end
)