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.:retry_exceptions(list ofatom/0) - Exception modules that should trigger a retry when raised. Defaults to[], meaning raised exceptions are not retried; use:retry/{:retry, reason}return values, or the:retry_onpredicate, to drive retries instead. 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()], 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.