Current section

Files

Jump to
oidcc src oidcc_backoff.erl
Raw

src/oidcc_backoff.erl

%%%-------------------------------------------------------------------
%% @doc Backoff Handling
%%
%% Based on `db_connection':
%% [https://github.com/elixir-ecto/db_connection/blob/8ef1f2ea54922873590b8939f2dad6b031c5b49c/lib/db_connection/backoff.ex#L24]
%% @end
%% @since 3.2.0
%%%-------------------------------------------------------------------
-module(oidcc_backoff).
-export_type([type/0]).
-export_type([min/0]).
-export_type([max/0]).
-export_type([state/0]).
-export([handle_retry/4]).
-type type() :: stop | exponential | random | random_exponential.
-type min() :: pos_integer().
-type max() :: pos_integer().
-opaque state() :: pos_integer() | {pos_integer(), pos_integer()}.
%% @private
-spec handle_retry(Type, Min, Max, State) -> stop | {Wait, State} when
Type :: type(), Min :: min(), Max :: max(), State :: undefined | state(), Wait :: pos_integer().
handle_retry(Type, Min, Max, State) when Min > 0, Max > 0, Max >= Min ->
priv_handle_retry(Type, Min, Max, State).
-spec priv_handle_retry(Type, Min, Max, State) -> stop | {Wait, State} when
Type :: type(), Min :: min(), Max :: max(), State :: undefined | state(), Wait :: pos_integer().
priv_handle_retry(stop, _Min, _Max, undefined) ->
stop;
priv_handle_retry(random, Min, Max, State) ->
{rand(Min, Max), State};
priv_handle_retry(exponential, Min, _Max, undefined) ->
{Min, Min};
priv_handle_retry(exponential, _Min, Max, State) ->
Wait = min(State * 2, Max),
{Wait, Wait};
priv_handle_retry(random_exponential, Min, Max, undefined) ->
Lower = max(Min, Max div 3),
priv_handle_retry(random_exponential, Min, Max, {Lower, Lower});
priv_handle_retry(random_exponential, _Min, Max, {Prev, Lower}) ->
NextMin = min(Prev, Lower),
NextMax = min(Prev * 3, Max),
Next = rand(NextMin, NextMax),
priv_handle_retry(random, NextMin, NextMax, {Next, Lower}).
rand(Min, Max) -> rand:uniform(Max - Min + 1) + Min - 1.