Skip to content

Instantly share code, notes, and snippets.

@isubas
Last active May 2, 2020 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isubas/4d079c7021be52756211af0b71a18605 to your computer and use it in GitHub Desktop.
Save isubas/4d079c7021be52756211af0b71a18605 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
module Utils
module Retry
RETRIABLE_DEFAULT_CONFIGURATION = {
on: [StandardError],
max_retries: 3,
sleep: 0,
exponential: true
}.freeze
RETRIABLE_CONFIG = Struct.new(:on, :max_retries, :sleep, :exponential, keyword_init: true) do
def sleep?
self.sleep.positive?
end
def sleep_value_for(val)
return (2**val) - 1 if exponential
self.sleep
end
end
def retriable(**config)
@_retriable_added = true
@_retriable_configuration = _retriable_configure_with(config)
end
def method_added(method_name)
return unless instance_variable_defined?('@_retriable_added') && @_retriable_added
raise 'No error defined for retry check' if @_retriable_configuration.on.empty?
_build_retriable_for(method_name, config: @_retriable_configuration.dup)
@_retriable_added = false
end
def _build_retriable_for(method_name, config:)
wrapper = Module.new do
define_method method_name do |*args|
@_tries ||= 0
super(*args)
rescue *config.on => e
@_tries = 0 && raise(e) unless (@_tries += 1) <= config.max_retries
sleep(config.sleep_value_for(@_tries - 1)) if config.sleep?
retry
end
end
prepend wrapper
end
private
def _retriable_configure_with(config)
config[:on] = [config[:on]] unless config[:on].is_a?(Array)
RETRIABLE_CONFIG.new(RETRIABLE_DEFAULT_CONFIGURATION.merge(config))
end
end
end
class Foo
extend Utils::Retry
retriable on: NoMethodError, max_retries: 10
def bar(a)
puts 'bar'
a.map(&:to_s)
end
retriable max_retries: 5, on: NoMethodError
def foo
puts 'foo'
nil.map(&:to_s)
end
retriable max_retries: 3, on: [NoMethodError, RuntimeError], exponential: true, sleep: 1
def try(a:)
puts a
a.map(&:to_s)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment