class ReeStd::Retry
def calculate_retry_interval
def calculate_retry_interval current_interval = @interval * (@backoff_factor ** @current_attempt) [@max_interval, current_interval].min end
def call(&block)
def call(&block) block.call rescue => e raise unless match_error?(e) raise unless has_attempts? @retry_block.call(@current_attempt, e) Kernel.sleep(calculate_retry_interval) increment_attemt! retry end
def has_attempts?
def has_attempts? @current_attempt < @max end
def increment_attemt!
def increment_attemt! @current_attempt += 1 end
def initialize(max:, **opts)
def initialize(max:, **opts) @max = max @current_attempt = 0 @interval = opts.fetch(:interval, 1) @max_interval = opts.fetch(:max_interval, Float::INFINITY) @backoff_factor = opts.fetch(:backoff_factor, 1) @exceptions = opts.fetch(:exceptions) { [StandardError].freeze } @retry_block = opts.fetch(:retry_block, Proc.new {}) @retry_if = opts.fetch(:retry_if, Proc.new { true }) end
def match_error?(e)
def match_error?(e) puts @retry_if.call(e) @retry_if.call(e) && @exceptions.any? { e.is_a? _1 } end