Skip to content

Instantly share code, notes, and snippets.

@hayesdavis
Created October 22, 2013 20:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hayesdavis/7107908 to your computer and use it in GitHub Desktop.
Save hayesdavis/7107908 to your computer and use it in GitHub Desktop.
class Retriable
class << self
def config(&block)
self.new(&block)
end
end
def initialize(&block)
max_attempts 5
retry_if { true }
backoff { 1 }
if block_given?
instance_eval(&block)
end
end
def max_attempts(value=nil)
if value.nil?
@max_attempts
else
@max_attempts = value
self
end
end
def retry_if(&block)
if block_given?
@retry_if = block
self
else
@retry_if
end
end
def backoff(&block)
if block_given?
@backoff = block
self
else
@backoff
end
end
def execute(&block)
attempts = 0
begin
attempts += 1
if block.arity == 1
yield(attempts-1)
else
yield
end
rescue => e
if attempts < max_attempts && should_retry?(e)
sleep(compute_backoff(attempts))
retry
else
raise e
end
end
end
private
def should_retry?(e)
@retry_if ? true : @retry_if.call(e)
end
def compute_backoff(attempts)
if @backoff.kind_of?(Proc)
@backoff.arity == 1 ? @backoff.call(attempts) : @backoff.call
else
0
end
end
end
r = Retriable.new {
max_attempts 3
retry_if {|e| e.kind_of?(DownError) }
backoff {|attempt| (attempt*0.5) + rand(1000)/1000.0 }
}
client = SomeClient.new
result = r.execute {
client.get_stuff
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment