GenRetry (gen_retry v1.4.0)
GenRetry provides utilities for retrying Elixir functions, with configurable delay and backoff characteristics.
Summary
Given a 0-arity function which raises an exception upon failure, retry/2
and retry_link/2 repeatedly executes the function until success is
reached or the maximum number of retries has occurred.
GenRetry.Task.async/2 and GenRetry.Task.Supervisor.async/3
provide drop-in replacements for Task.async/1 and
Task.Supervisor.async/2, respectively, adding retry capability.
They return plain %Task{} structs, usable with any other function in
the Task module.
Examples
my_background_function = fn ->
:ok = try_to_send_tps_reports()
end
GenRetry.retry(my_background_function, retries: 10, delay: 10_000)
my_future_function = fn ->
{:ok, val} = get_val_from_flaky_network_service()
val
end
t = GenRetry.Task.async(my_future_function, retries: 3)
my_val = Task.await(t) # may raise exceptionInstallation
Add GenRetry to your list of dependencies in
mix.exs:def deps do [{:gen_retry, "~> 1.4.0"}] endEnsure GenRetry is started before your application:
def application do [applications: [:gen_retry]] end(Optional) Specify a custom logging module in your config.exs
config :gen_retry, GenRetry.Logger, logger: MyApp.CustomLoggerwhere MyApp.CustomLogger implements the GenRetry.Logger behavior. The default module is GenRetry.Utils if none is specified in a config.
Options
:retries, integer (default 1): Number of times to retry upon failure. Set to 0 to try exactly once; set to:infinityto retry forever.:delay, integer (default 1000): Number of milliseconds to wait between first failure and first retry. Subsequent retries use this value as a starting point for exponential backoff.:jitter, number (default 0): Proportion of current retry delay to randomly add to delay time. For example, given optionsdelay: 1000, jitter: 0.1, the first delay will be a random time between 1000 and 1100 milliseconds. Values under 0 will remove time rather than add it; beware of values under -1, which may result in nonsensical "negative time delays".:exp_base, number (default 2): The base to use for exponentiation during exponential backoff. Set to1to disable backoff. Values less than 1 are not very useful.:respond_to, pid (ignored byGenRetry.Task.*): The process ID to which a message should be sent upon completion. Successful exits send{:success, return_value, final_retry_state}; unsuccessful exits send{:failure, error, stacktrace, final_retry_state}.:on_success,fn {result, final_retry_state} -> nil end(default no-op): A function to run on success. The argument is a tuple containing the result and the final retry state.:on_failure,fn {exception, stacktrace, final_retry_state} -> nil end(default no-op): A function to run on failure. The argument is a tuple containing the exception, stacktrace, and final retry state.
Link to this section Summary
Functions
Starts a retryable process linked to GenRetry.Supervisor, and returns its
pid. fun should be a function that raises an exception upon failure;
any other return value is treated as success.
Starts a retryable process linked to the current process, and returns its
pid. fun should be a function that raises an exception upon failure;
any other return value is treated as success.
Link to this section Types
failure_msg()
Specs
failure_msg() ::
{:failure, Exception.t(), [:erlang.stack_item()], GenRetry.State.t()}
on_failure()
Specs
on_failure() ::
({exception :: any(), stacktrace :: list(),
final_retry_state :: GenRetry.State.t()} ->
any())
on_success()
Specs
on_success() ::
({result :: any(), final_retry_state :: GenRetry.State.t()} -> any())
option()
Specs
option() ::
{:retries, :infinity | non_neg_integer()}
| {:delay, non_neg_integer()}
| {:jitter, number()}
| {:exp_base, number()}
| {:respond_to, pid()}
| {:on_success, on_success()}
| {:on_failure, on_failure()}
options()
Specs
options() :: [option()]
retryable_fun()
Specs
success_msg()
Specs
success_msg() :: {:success, any(), GenRetry.State.t()}
Link to this section Functions
retry(fun, opts \\ [])
Specs
retry(retryable_fun(), options()) :: pid()
Starts a retryable process linked to GenRetry.Supervisor, and returns its
pid. fun should be a function that raises an exception upon failure;
any other return value is treated as success.
retry_link(fun, opts \\ [])
Specs
retry_link(retryable_fun(), options()) :: pid()
Starts a retryable process linked to the current process, and returns its
pid. fun should be a function that raises an exception upon failure;
any other return value is treated as success.