Created
October 3, 2008 17:22
-
-
Save jashmenn/14584 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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