Skip to content

Instantly share code, notes, and snippets.

@jashmenn
Created October 3, 2008 17:22
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 jashmenn/14584 to your computer and use it in GitHub Desktop.
Save jashmenn/14584 to your computer and use it in GitHub Desktop.
# exponential random backoff ala ethernet
# Nate Murray, 2008
# inspired by code found in http://files.rubyforge.vm.bytemark.co.uk/rhb/xmpphttpbind.rb
class EthernetBackoff
class Error < StandardError
end
# Retries block with exponential random backoff ala ethernet The retry is
# based on the return value of &block. If the value evaluates to a boolean
# true then the value is returned. Otherwise it will sleep for the calculated
# time.
#
# The +attempt+ number and +next_backoff_time+ are yielded to the block.
# +next_backoff_time+ is useful if you want to say how much longer you are going to sleep
# if the value of your block was false. +attempt+ starts at 0.
#
# Example usage:
#
# value = EthernetBackoff.backoff(retries=5) do |attempt, backoff_time|
# if attempt + 1 == 3
# "happy brick"
# else
# STDERR.puts("something failed " + "#{attempt+1}/#{retries} (backing off " + "#{sprintf("%.2f", backoff_time)} seconds)")
# false
# end
# end
#
# value.should eql("happy brick")
#
def self.backoff(retries=10, retry_period=0.5, opts={}, &block)
retries.times do |attempt|
next_backoff_time = rand * retry_period * (2 ** attempt)
value = yield attempt, next_backoff_time
if value # then we're done
return value
else # we need to try again
sleep(next_backoff_time)
end
end
# if we're here then we failed
raise Error, "Retrying failed after #{retries} times. "
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment