Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

backoff

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

backoff - npm Package Compare versions

Comparing version 0.0.3 to 0.1.0

examples/randomized.js

91

backoff.js

@@ -13,66 +13,75 @@ /*

function ExponentialBackoff(options) {
/**
* Fibonacci back off.
*/
function Backoff(options) {
events.EventEmitter.call(this);
options = options || {};
if (isDef(options.initialTimeout) && options.initialTimeout < 1) {
if (isDef(options.initialDelay) && options.initialDelay < 1) {
throw new Error('The initial timeout must be greater than 0.');
} else if (isDef(options.maxTimeout) && options.maxTimeout < 1) {
} else if (isDef(options.maxDelay) && options.maxDelay < 1) {
throw new Error('The maximal timeout must be greater than 0.');
}
this.initialTimeout = options.initialTimeout || 100;
this.maxTimeout = options.maxTimeout || 10000;
this.initialDelay_ = options.initialDelay || 100;
this.maxDelay_ = options.maxDelay || 10000;
if (this.maxTimeout <= this.initialTimeout) {
throw new Error('The maximal timeout must be greater ' +
'than the the initial timeout.');
if (this.maxDelay_ <= this.initialDelay_) {
throw new Error('The maximal backoff delay must be ' +
'greater than the initial backoff delay.');
}
this.backoffInProgress = false;
this.backoffNumber = 0;
this.backoffDelay = 0;
this.timeoutID = -1;
if (isDef(options.randomisationFactor) &&
(options.randomisationFactor < 0 || options.randomisationFactor > 1)) {
throw new Error('The randomisation factor must be between 0 and 1.');
}
this.randomisationFactor_ = options.randomisationFactor || 0;
this.backoffDelay_ = 0;
this.randomizedDelay_ = 0;
this.nextBackoffDelay_ = this.initialDelay_;
this.backoffNumber_ = 0;
this.timeoutID_ = -1;
this.handlers = {
backoff: this.onBackoff.bind(this)
backoff: this.onBackoff_.bind(this)
};
}
util.inherits(ExponentialBackoff, events.EventEmitter);
util.inherits(Backoff, events.EventEmitter);
ExponentialBackoff.prototype.EXPONENTIAL_FACTOR = 2;
ExponentialBackoff.prototype.updateBackoffDelay = function() {
if (this.backoffDelay < this.maxTimeout) {
var multiplicativeFactor = Math.pow(this.EXPONENTIAL_FACTOR, this.backoffNumber);
var delay = Math.min(this.initialTimeout * multiplicativeFactor, this.maxTimeout);
this.backoffDelay = Math.round(delay);
Backoff.prototype.backoff = function() {
if (this.timeoutID_ !== -1) {
throw new Error('Backoff in progress.');
}
};
ExponentialBackoff.prototype.backoff = function() {
if (this.backoffInProgress) {
throw new Error('Backoff in progress.');
}
this.updateBackoffDelay();
this.timeoutID = setTimeout(this.handlers.backoff, this.backoffDelay);
this.backoffInProgress = true;
this.backoffNumber++;
this.backoffNumber_++;
var backoffDelay = Math.min(this.nextBackoffDelay_, this.maxDelay_);
this.nextBackoffDelay_ += this.backoffDelay_;
this.backoffDelay_ = backoffDelay;
var randomisationMultiple = 1 + Math.random() * this.randomisationFactor_;
this.randomizedDelay_ = Math.round(backoffDelay * randomisationMultiple);
this.timeoutID_ = setTimeout(this.handlers.backoff, this.randomizedDelay_);
};
ExponentialBackoff.prototype.onBackoff = function(delay) {
this.backoffInProgress = false;
this.emit('backoff', this.backoffNumber, this.backoffDelay);
Backoff.prototype.onBackoff_ = function() {
this.timeoutID_ = -1;
this.emit('backoff', this.backoffNumber_, this.randomizedDelay_);
};
ExponentialBackoff.prototype.reset = function() {
this.backoffInProgress = false;
clearTimeout(this.timeoutID);
this.backoffNumber = 0;
this.backoffDelay = 0;
this.emit('reset');
Backoff.prototype.reset = function() {
clearTimeout(this.timeoutID_);
this.timeoutID_ = -1;
this.backoffNumber_ = 0;
this.nextBackoffDelay_ = this.initialDelay_;
this.randomizedDelay_ = 0;
this.backoffDelay_ = 0;
};
module.exports = ExponentialBackoff;
module.exports = Backoff;

@@ -6,4 +6,4 @@ #!/usr/bin/env node

var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 1000
initialDelay: 10,
maxDelay: 1000
});

@@ -10,0 +10,0 @@

{
"name": "backoff",
"description": "Exponential backoff implementation.",
"version": "0.0.3",
"description": "Fibonnaci backoff implementation.",
"version": "0.1.0",
"author": "Mathieu Turcotte <turcotte.mat@gmail.com>",
"keywords": ["backoff", "exponential"],
"keywords": ["backoff", "fibonnaci"],
"repository": {

@@ -12,3 +12,3 @@ "type": "git",

"devDependencies": {
"sinon": "1.3",
"sinon": "1.4",
"nodeunit": "0.7",

@@ -15,0 +15,0 @@ "jshint": "0.7"

@@ -1,4 +0,4 @@

# Exponential backoff implementation for Node.js [![Build Status](https://secure.travis-ci.org/MathieuTurcotte/node-backoff.png?branch=master)](http://travis-ci.org/MathieuTurcotte/node-backoff)
# Backoff for Node.js [![Build Status](https://secure.travis-ci.org/MathieuTurcotte/node-backoff.png?branch=master)](http://travis-ci.org/MathieuTurcotte/node-backoff)
An exponential backoff implementation for Node.js.
Fibonnaci backoff implementation for Node.js.

@@ -24,4 +24,5 @@ ## Installation

var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 1000
randomisationFactor: 0,
initialDelay: 10,
maxDelay: 1000
});

@@ -32,3 +33,3 @@

if (number < 10) {
if (number < 12) {
backoff.backoff();

@@ -45,13 +46,18 @@ }

1 10ms
2 20ms
3 40ms
4 80ms
5 160ms
6 320ms
7 640ms
8 1000ms
9 1000ms
10 1000ms
2 10ms
3 20ms
4 30ms
5 50ms
6 80ms
7 130ms
8 210ms
9 340ms
10 550ms
11 890ms
12 1000ms
```
Backoff objects are meant to be instantiated once and reused several times
by calling `reset` after each successful backoff operation.
## API

@@ -67,21 +73,31 @@

options = {
initialTimeout: 100,
maxTimeout: 10000
randomisationFactor: 0,
initialDelay: 100,
maxDelay: 10000
};
```
With these values, the timeout delay will exponentially increase from 100ms to
1000ms.
With these values, the backoff delay will increase from 100ms to 10000ms. The
randomisation factor controls the range of randomness and must be between 0
and 1. By default, no randomisation is applied on the backoff delay.
### backoff.backoff()
Start a backoff operation, doubling the previous timeout.
Start a backoff operation. Will throw an error if a backoff operation is already
in progress.
Returns true on success and false if a backoff was already in progress.
In practice, this method should be called after a failed attempt to perform a
sensitive operation (connecting to a database, downloading a resource over the
network, etc.).
### backoff.reset()
Reset the backoff object state. If a backoff operation is in progress when
called, it will be stop. After reset, a backoff instance can be reused.
Reset the backoff delay to the initial backoff delay and stop any backoff
operation in progress. After reset, a backoff instance can and should be
reused.
In practice, this method should be called after having successfully completed
the sensitive operation guarded by the backoff instance or if the client code
request to stop any reconnection attempt.
### Event: 'backoff'

@@ -92,10 +108,7 @@

Emitted on backoff completion.
Emitted on backoff completion, effectively signaling that the failing operation
should be retried.
### Event: 'reset'
Emitted when a backoff instance is reset.
## License
This code is free to use under the terms of the [MIT license](http://mturcotte.mit-license.org/).

@@ -21,5 +21,5 @@ /*

"'backoff' event should be emitted on backoff completion": function(test) {
"backoff event should be emitted on backoff completion": function(test) {
var backoff = new Backoff({
initialTimeout: 10
initialDelay: 10
});

@@ -36,17 +36,6 @@ var spy = new sinon.spy();

"'reset' event should be emitted on reset": function(test) {
var backoff = new Backoff();
var reset = sinon.spy();
backoff.on('reset', reset);
backoff.reset();
test.ok(reset.calledOnce, 'reset event has not been emitted');
test.done();
},
"the backoff delay should increase exponentially from initialTimeout to maxTimeout": function(test) {
"the backoff delay should follow a Fibonacci sequence": function(test) {
var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 1000
initialDelay: 10,
maxDelay: 1000
});

@@ -56,4 +45,5 @@ var spy = new sinon.spy();

// Fibonnaci sequence: x[i] = x[i-1] + x[i-2].
var delays = [10, 10, 20, 30, 50, 80, 130, 210, 340, 550, 890, 1000];
var clock = this.clock;
var delays = [10, 20, 40, 80, 160, 320, 640, 1000, 1000];

@@ -73,6 +63,6 @@ delays.forEach(function(delay, i) {

"the initial timeout should be greater than 0": function(test) {
"the initial backoff delay should be greater than 0": function(test) {
test.throws(function() {
var backoff = new Backoff({
initialTimeout: -1
initialDelay: -1
});

@@ -83,3 +73,3 @@ });

var backoff = new Backoff({
initialTimeout: 0
initialDelay: 0
});

@@ -90,3 +80,3 @@ });

var backoff = new Backoff({
initialTimeout: 1
initialDelay: 1
});

@@ -98,6 +88,6 @@ });

"the maximal timeout should be greater than 0": function(test) {
"the maximal backoff delay should be greater than 0": function(test) {
test.throws(function() {
var backoff = new Backoff({
maxTimeout: -1
maxDelay: -1
});

@@ -108,3 +98,3 @@ });

var backoff = new Backoff({
maxTimeout: 0
maxDelay: 0
});

@@ -116,7 +106,7 @@ });

"the maximal timeout should be greater than the original timeout": function(test) {
"the maximal backoff delay should be greater than the initial backoff delay": function(test) {
test.throws(function() {
var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 10
initialDelay: 10,
maxDelay: 10
});

@@ -127,4 +117,4 @@ });

var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 11
initialDelay: 10,
maxDelay: 11
});

@@ -136,2 +126,24 @@ });

"the randomisation factor should be between 0 and 1": function(test) {
test.throws(function() {
var backoff = new Backoff({
randomisationFactor: -0.1
});
});
test.throws(function() {
var backoff = new Backoff({
randomisationFactor: 1.1
});
});
test.doesNotThrow(function() {
var backoff = new Backoff({
randomisationFactor: 0.5
});
});
test.done();
},
"call to backoff while a backoff is in progress should throw an error": function(test) {

@@ -148,5 +160,5 @@ var backoff = new Backoff();

"calling reset when a backoff is in progress should disarm the timeout": function(test) {
"calling reset when a backoff is in progress should cancel its execution": function(test) {
var backoff = new Backoff({
initialTimeout: 10
initialDelay: 10
});

@@ -162,3 +174,3 @@

test.equals(spy.callCount, 0, "backoff timeout did trigger");
test.equals(spy.callCount, 0, "backoff did trigger");
test.done();

@@ -169,4 +181,4 @@ },

var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 1000
initialDelay: 10,
maxDelay: 1000
});

@@ -185,3 +197,3 @@ var spy = new sinon.spy();

// Skip the initial timeout value.
// Skip the initial backoff delay.
this.clock.tick(10);

@@ -188,0 +200,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc