attempt v0.2.0 Attempt
Limitations
This implementation has some limitations that will be progressively removed:
No backoff strategy is employed for the retry, retries are controlled by the configured token bucket.
No jitter is introduced in the bucket algorithm
No leaky bucket token implementation. The provided token bucket implementation allows for a burst of invokations up to the overall bucket size but it maintains an average execution rate. A leaky bucket token implementation alternative would not allow a burst rate which in some cases would be a better strategy.
Link to this section Summary
Functions
Execute a function in the context of a retry budget
Link to this section Functions
Execute a function in the context of a retry budget.
A retry budget has two compoents:
a
token bucket
which acts to provide retry throttlnh for any retriesa number of allowable
retries
that are performed when a failure exit is detected from the function
The given function will be executed until a successful return is detected or the maximum number of tries is exceeded or if no token could be claimed.
Arguments
fun
is an anonymous function or function reference to be executed.options
is a keyword list of options to configure the retry budget
Options
tries
is the number of times the function will be executed if an error is returned from the functiontoken_bucket
is the token bucket used to throttle the execution rate. Currently only one token bucket is implemented. SeeAttempt.Bucket.Token
retry_policy
is a module that implements theAttempt.Retry
behaviour to classify the return value from thefun
as either:return
,:retry
orreraise
. The defaultretry_policy
isAttempt.Retry.DefaultPolicy
.
Default options
If not supplied the default options are:
:tries
is1
:token_bucket
isAttempt.Bucket.Token.new(@default_bucket_name)
:retry_policy
isAttempt.Retry,DefaultPolicy
Retry policy actions
In order to ascertain whether a function should be retried each return value
needs to be classified. The classification is the responsibility of the
:retry_policy
module. Three classifications are available:
:return
means that the return value of the function is considered a success and it returned to the called:retry
means that a failure return was detected but that the failure is considered transient and is therefore eligble to be retried:reraise
means that an exception was detected and the execption is not considered transient. Therefore the exception should be re-raised.
See also Attempt.Retry.Exception
which defines a protocol for determining
the classification of exceptions and Attempt.Retry.DefaultPolicy
which
implements the default classifier.
Examples
iex#> Attempt.execute fn -> "Hello World" end
"Hello World"
iex#> Attempt.execute fn -> IO.puts "Reraise Failure!"; div(1,0) end, tries: 3
Reraise Failure!
** (ArithmeticError) bad argument in arithmetic expression
:erlang.div(1, 0)
(attempt) lib/attempt.ex:119: Attempt.execute_function/1
(attempt) lib/attempt.ex:98: Attempt.execute/6
iex#> Attempt.execute fn -> IO.puts "Try 3 times"; :error end, tries: 3
Try 3 times
Try 3 times
Try 3 times
:error
# Create a bucket that adds a new token only every 10 seconds
iex#> {:ok, bucket} = Attempt.Bucket.Token.new :test, fill_rate: 10_000
iex#> Attempt.execute fn ->
IO.puts "Try 11 times and we'll timeout claiming a token"
:error
end, tries: 11, token_bucket: bucket
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
Try 11 times and we'll timeout claiming a token
{:error, {:timeout, {GenServer, :call, [:test, :claim_token, 5000]}}}