Options that control retry logic for calls to external services.
Retry options can be given either as this struct or as a plain keyword list
(which is validated and converted with new/1). The available options are:
:backoff- The backoff strategy used to grow the delay between retries. The default value is:exponential.:base(non_neg_integer/0) - The initial delay between retries, in milliseconds (0for no delay). The default value is10.:factor(pos_integer/0) - Growth factor applied on each retry. Only used for:linearbackoff. The default value is1.:cap(pos_integer/0) - Caps the delay between retries to at most this many milliseconds.:expiry- Total time budget for retries, in milliseconds. Retrying stops once exceeded. Defaults to no time budget;:infinitystates that explicitly (see the note on unbounded retries below).:max_attempts- Maximum number of attempts (the initial attempt plus retries). Defaults to no limit;:infinitystates that explicitly (see the note on unbounded retries below).:jitter- Random jitter applied to delays.trueapplies +/- 10%; a float (e.g.0.25) applies that proportion. Helps avoid retrying in lockstep (thundering herd). The default value isfalse.:retry_on(function of arity 1) - A predicate run on the return value of the call. When it returns a truthy value the call is retried, exactly as if the function had returned:retry(the result itself is used as the retry reason, and the circuit breaker melts). Lets you drive retries from a function that was not written to return:retry/{:retry, reason}. Defaults to no predicate. An explicit:retry/{:retry, reason}return always takes precedence over the predicate. A predicate that fails — raising, throwing, or exiting rather than answering — is treated as no match, leaving the result untouched, and logs a warning.:retry_exceptions- Which raised exceptions should trigger a retry, as either a list of exception modules or a predicate run on the exception itself. A predicate can decide per instance rather than per type — useful when the same exception type is sometimes transient and sometimes not. Defaults to[], meaning raised exceptions are not retried; use:retry/{:retry, reason}return values, or the:retry_onpredicate, to drive retries instead. An exception that is not matched also does not melt the circuit breaker, and once retries are spent the original exception is re-raised with its original stacktrace. A predicate that fails — raising, throwing, or exiting rather than answering — is treated as no match, so the exception it was asked to classify reaches the caller unchanged, and a warning is logged. The default value is[].
Unbounded retries
Neither :max_attempts nor :expiry has a default, so options that set
neither place no bound on retrying: a call that keeps returning :retry
keeps retrying forever. The circuit breaker is not a reliable backstop for
this — exponential backoff widens the gap between attempts until failures no
longer accumulate fast enough to open it. Almost always, you want one of these
set. See Bounding retries for the details.
ExternalService.start/2 logs a warning when a service's default retry
options leave both unset. If unbounded retrying really is what you want — or
every call site supplies its own bound — say so explicitly with :infinity,
which behaves identically but silences the warning:
ExternalService.start(:my_service, retry: [max_attempts: :infinity])
Summary
Functions
Layers a keyword list of per-call overrides onto a base struct.
Builds a validated RetryOptions struct from a keyword list (or returns an
existing struct unchanged).
Types
@type t() :: %ExternalService.RetryOptions{ backoff: :exponential | :linear, base: non_neg_integer(), cap: pos_integer() | nil, expiry: pos_integer() | :infinity | nil, factor: pos_integer(), jitter: boolean() | float(), max_attempts: pos_integer() | :infinity | nil, retry_exceptions: [module()] | (Exception.t() -> as_boolean(term())), retry_on: (term() -> as_boolean(term())) | nil }
Functions
Layers a keyword list of per-call overrides onto a base struct.
Only the keys actually present in opts are overridden; every other field is
taken from base. This is how per-call retry options tweak — rather than
reset — a service's configured defaults. A %RetryOptions{} given in place of
the keyword list replaces base wholesale, since a struct is already a
complete set of options.
Raises NimbleOptions.ValidationError if opts is invalid.
Builds a validated RetryOptions struct from a keyword list (or returns an
existing struct unchanged).
Raises NimbleOptions.ValidationError if the options are invalid.