Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
.vscode/
6 changes: 6 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
var Backoff = require('./lib/backoff');
var ExponentialBackoffStrategy = require('./lib/strategy/exponential');
var FibonacciBackoffStrategy = require('./lib/strategy/fibonacci');
var InverseExponentialBackoffStrategy = require('./lib/strategy/inverse_exponential');
var FunctionCall = require('./lib/function_call.js');

module.exports.Backoff = Backoff;
Expand All @@ -21,6 +22,11 @@ module.exports.exponential = function(options) {
return new Backoff(new ExponentialBackoffStrategy(options));
};

// Constructs an inverse exponential backoff.
module.exports.inverseExponential = function(options) {
return new Backoff(new InverseExponentialBackoffStrategy(options));
};

// Constructs a FunctionCall for the given function and arguments.
module.exports.call = function(fn, vargs, callback) {
var args = Array.prototype.slice.call(arguments);
Expand Down
38 changes: 38 additions & 0 deletions lib/strategy/inverse_exponential.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
var util = require('util');
var precond = require('precond');

var BackoffStrategy = require('./strategy');

// Inverse Exponential backoff strategy.
function InverseExponentialBackoffStrategy (options) {
BackoffStrategy.call(this, options);
this.backoffDelay_ = 512;
this.nextBackoffDelay_ = this.getInitialDelay();
this.factor_ = InverseExponentialBackoffStrategy.DEFAULT_FACTOR;

if (options && options.factor !== undefined) {
precond.checkArgument(options.factor > 1,
'Exponential factor should be greater than 1 but got %s.',
options.factor);
this.factor_ = options.factor;
}
}
util.inherits(InverseExponentialBackoffStrategy, BackoffStrategy);

// Default division factor used to compute the next backoff delay from
// the current one. The value can be overridden by passing a custom factor as
// part of the options.
InverseExponentialBackoffStrategy.DEFAULT_FACTOR = 2;

InverseExponentialBackoffStrategy.prototype.next_ = function () {
this.backoffDelay_ = Math.max(this.nextBackoffDelay_, 0);
this.nextBackoffDelay_ = parseInt(this.backoffDelay_ / this.factor_);
return this.backoffDelay_;
};

InverseExponentialBackoffStrategy.prototype.reset_ = function () {
this.backoffDelay_ = 512;
this.nextBackoffDelay_ = this.getInitialDelay();
};

module.exports = InverseExponentialBackoffStrategy;
66 changes: 36 additions & 30 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
{
"name": "backoff",
"description": "Fibonacci and exponential backoffs.",
"version": "2.5.0",
"license": "MIT",
"author": "Mathieu Turcotte <[email protected]>",
"keywords": ["backoff", "retry", "fibonacci", "exponential"],
"repository": {
"type": "git",
"url": "https://github.com/MathieuTurcotte/node-backoff.git"
},
"dependencies": {
"precond": "0.2"
},
"devDependencies": {
"sinon": "1.10",
"nodeunit": "0.9"
},
"scripts": {
"docco" : "docco lib/*.js lib/strategy/* index.js",
"pretest": "jshint lib/ tests/ examples/ index.js",
"test": "node_modules/nodeunit/bin/nodeunit tests/"
},
"engines": {
"node": ">= 0.6"
},
"files": [
"index.js",
"lib",
"tests"
]
"name": "backoff",
"description": "Fibonacci and exponential backoffs.",
"version": "2.5.0",
"license": "MIT",
"author": "Mathieu Turcotte <[email protected]>",
"keywords": [
"backoff",
"retry",
"fibonacci",
"exponential"
],
"repository": {
"type": "git",
"url": "https://github.com/MathieuTurcotte/node-backoff.git"
},
"dependencies": {
"precond": "0.2"
},
"devDependencies": {
"jshint": "2.9.5",
"nodeunit": "0.9",
"sinon": "1.10"
},
"scripts": {
"docco": "docco lib/*.js lib/strategy/* index.js",
"pretest": "jshint lib/ tests/ examples/ index.js",
"test": "node_modules/nodeunit/bin/nodeunit tests/"
},
"engines": {
"node": ">= 0.6"
},
"files": [
"index.js",
"lib",
"tests"
]
}
58 changes: 58 additions & 0 deletions tests/inverse_exponential_backoff_strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
*
* Licensed under the MIT license.
*/

var sinon = require('sinon');

var InverseExponentialBackoffStrategy = require('../lib/strategy/inverse_exponential');

exports["InverseExponentialBackoffStrategy"] = {

"backoff delays should follow an inverse exponential sequence": function(test) {
var strategy = new InverseExponentialBackoffStrategy({
initialDelay: 512
});

// sequence: x[i] = x[i-1] / 2.
var expectedDelays = [512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0];
var actualDelays = expectedDelays.map(function () {
return strategy.next();
});

test.deepEqual(expectedDelays, actualDelays,
'Generated delays should follow an exponential sequence.');
test.done();
},

"backoff delay factor should be configurable": function (test) {
var strategy = new InverseExponentialBackoffStrategy({
initialDelay: 1024,
factor: 4
});

// Exponential sequence: x[i] = x[i-1] / 4.
var expectedDelays = [1024, 256, 64, 16, 4, 1, 0];
var actualDelays = expectedDelays.map(function () {
return strategy.next();
});

test.deepEqual(expectedDelays, actualDelays,
'Generated delays should follow a configurable exponential sequence.');
test.done();
},

"backoff delays should restart from the initial delay after reset": function(test) {
var strategy = new InverseExponentialBackoffStrategy({
initialDelay: 512
});

strategy.next();
strategy.reset();

var backoffDelay = strategy.next();
test.equals(backoffDelay, 512,
'Strategy should return the initial delay after reset.');
test.done();
}
};