Reattempt
A jittery Enumerable retry and backoff library
Reattempt is a simple application of Ruby’s Enumerators to provide a nice idiomatic interface to retries. At its most basic:
begin
Reattempt::Retry.new.each do
poke_remote_api
end
rescue Reattempt::RetriesExceeded => e
handle_repeated_failure(e.cause)
end
It’s split into two Enumerables - Retry
implements the retrying Exception-catching
iterator, while Backoff
implements the configurable jittered exponential backoff,
allowing the API user to implement sleeping as they see fit:
# Start delay 0.075-0.125 seconds, increasing to 0.75-1.25 seconds
bo = Reattempt::Backoff.new(min_delay: 0.1, max_delay: 1.0, jitter: 0.5)
bo.take(4).map { x.round(4) } # => [0.1138, 0.2029, 0.4227, 0.646]
bo.take(2).each { sleep delay }
bo.delay_for_attempt(4) # => 1.0403524624141058
bo[4] # => 0.8328055668923606
bo.each do
printf(, delay)
sleep delay
end
A more complete example:
bo = Reattempt::Backoff.new(min_delay: 0.1, max_delay: 1.0, jitter: 0.5)
try = Reattempt::Retry.new(tries: 5, rescue: TempError, backoff: bo)
begin
try.each do
raise TempError,
end
rescue Reattempt::RetriesExceeded => e
p e.cause # => #<TempError: "Failed in attempt 5">
end