1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
# frozen_string_literal: true
module Retriable
class ExponentialBackoff
ATTRIBUTES = %i[
tries
base_interval
multiplier
max_interval
rand_factor
].freeze
attr_accessor(*ATTRIBUTES)
def initialize(opts = {})
@tries = 3
@base_interval = 0.5
@max_interval = 60
@rand_factor = 0.5
@multiplier = 1.5
opts.each do |k, v|
raise ArgumentError, "#{k} is not a valid option" if !ATTRIBUTES.include?(k)
instance_variable_set(:"@#{k}", v)
end
end
def intervals
intervals = Array.new(tries) do |iteration|
[base_interval * (multiplier**iteration), max_interval].min
end
return intervals if rand_factor.zero?
intervals.map { |i| randomize(i) }
end
private
def randomize(interval)
delta = rand_factor * interval.to_f
min = interval - delta
max = interval + delta
rand(min..max)
end
end
end
|