No commit activity in last 3 years
No release in over 3 years
Exponential backoff algorithm for better reconnect intervals.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

 Project Readme

Exponential Backoff

Build Status Gem Version

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