Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master

README.md

Exponential Backoff

Build Status

Too lazy to make retries to external services in a fashion that providers recommend? Never heard of exponential backoff technique? Now there is no excuse not to be nice.

Installation

Add this line to your application's Gemfile:

gem 'exponential-backoff'

And then execute:

$ bundle

Or install it yourself as:

$ gem install exponential-backoff

Usage

Start with specifying minimal and maximal intervals, that is 4s and 60s respectively:

minimal_interval = 4.0
maximal_elapsed_time = 60.0

backoff = ExponentialBackoff.new(minimal_interval, maximal_elapsed_time)

Arrays and ranges work for your convenience too:

backoff = ExponentialBackoff.new(minimal_interval..maximal_elapsed_time)
backoff = ExponentialBackoff.new([minimal_interval, maximal_elapsed_time])

You can get intervals for specified range:

backoff.intervals_for(0..5) # [4.0, 8.0, 16.0, 32.0, 60.0, 60.0]

Enumerate on them:

backoff.intervals.each do |interval|
  sleep(interval)
end

Or just get interval for requested, that is 3rd, iteration:

backoff.interval_at(3) # 32.0

Intervals don't exceed maximal allowed time:

backoff.interval_at(20) # 60.0

Backoff instance maintains state, you can ask for next interval...

backoff.next_interval # 4.0
backoff.next_interval # 8.0

...and reset it to start from beginning

backoff.clear
backoff.next_interval # 4.0

Finally you can specify interval multiplier and randomization factor:

backoff = ExponentialBackoff.new(min_interval, max_elapsed)
backoff.multiplier = 1.5
backoff.randomize_factor = 0.25

backoff.intervals_for(0..2) # [3.764, 6.587, 9.76]

You can peek what is the current interval:

backoff.current_interval # 3.764

You can check if given iteration is one of intervals or maximum interval multiple:

backoff = ExponentialBackoff.new(1, 10)
backoff.iteration_active?(4) # true
backoff.iteration_active?(20) # true
backoff.iteration_active?(3) # false

There is also sugar for executing block of code until successful with increasing intervals:

backoff.until_success do |interval, retry_count|
  # do your thing
  # when last line in block evaluates to true, elapsed time clear and loop breaks
  # when false, increase interval and retry

  # you can break loop earlier if you want,
  # `nil` return value is considered a success
  return if retry_count > 3
end

Running tests

bundle exec rake test

Supported rubies

Targets all Rubies (including Rubinius and JRuby) provided it's at least 1.9 mode.

Something went wrong with that request. Please try again.