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.1 to 0.0.2

43

backoff.js

@@ -14,16 +14,33 @@ /*

this.exponentialFactor = options.exponentialFactor || 2;
if (options.initialTimeout != undefined && options.initialTimeout < 1) {
throw new Error('The initial timeout must be greater than 0.');
} else if (options.maxTimeout != undefined && options.maxTimeout < 1) {
throw new Error('The maximal timeout must be greater than 0.');
}
this.initialTimeout = options.initialTimeout || 100;
this.maxTimeout = options.maxTimeout || 10000;
if (this.maxTimeout <= this.initialTimeout) {
throw new Error('The maximal timeout must be greater ' +
'than the the initial timeout.');
}
this.backoffInProgress = false;
this.backoffNumber = 0;
this.backoffDelay = 0;
this.timeoutID = -1;
this.handlers = {
backoff: this.onBackoff.bind(this)
};
};
util.inherits(ExponentialBackoff, events.EventEmitter);
ExponentialBackoff.prototype.calculateBackoffDelay = function() {
var multiplicativeFactor = Math.pow(this.exponentialFactor, this.backoffNumber);
var delay = Math.min(this.initialTimeout * multiplicativeFactor, this.maxTimeout);
return Math.round(delay);
ExponentialBackoff.prototype.updateBackoffDelay = function() {
if (this.backoffDelay < this.maxTimeout) {
var multiplicativeFactor = Math.pow(2, this.backoffNumber);
var delay = Math.min(this.initialTimeout * multiplicativeFactor, this.maxTimeout);
this.backoffDelay = Math.round(delay);
}
};

@@ -33,11 +50,8 @@

if (this.backoffInProgress) {
return false;
} else {
var delay = this.calculateBackoffDelay();
var onBackoff = this.onBackoff.bind(this, delay);
this.timeoutID = setTimeout(onBackoff, delay);
this.backoffInProgress = true;
this.backoffNumber++;
return true;
throw new Error('Backoff in progress.');
}
this.updateBackoffDelay();
this.timeoutID = setTimeout(this.handlers.backoff, this.backoffDelay);
this.backoffInProgress = true;
this.backoffNumber++;
};

@@ -47,3 +61,3 @@

this.backoffInProgress = false;
this.emit('backoff', this.backoffNumber, delay);
this.emit('backoff', this.backoffNumber, this.backoffDelay);
};

@@ -55,2 +69,3 @@

this.backoffNumber = 0;
this.backoffDelay = 0;
this.emit('reset');

@@ -57,0 +72,0 @@ };

{
"name": "backoff",
"description": "Exponential backoff implementation.",
"version": "0.0.1",
"version": "0.0.2",
"author": "Mathieu Turcotte <turcotte.mat@gmail.com>",

@@ -6,0 +6,0 @@ "keywords": ["backoff", "exponential"],

@@ -12,14 +12,24 @@ # Exponential backoff implementation for Node.js

The Backoff object inherits from EventEmitter. One can listen for
backoff completion by listening for 'backoff' events. Registered handlers
will be called with the current backoff number and delay.
In order to use backoff, require `backoff`.
``` js
```js
var Backoff = require('backoff');
```
var backoff = new Backoff();
`Backoff` inherits from `EventEmitter`. One can listen for backoff completion
by listening for `backoff` events. Registered handlers will be called with the
current backoff number and delay.
``` js
var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 1000
});
backoff.on('backoff', function(number, delay) {
// Retry operation...
backoff.backoff();
console.log(number + ' ' + delay + 'ms');
if (number < 10) {
backoff.backoff();
}
});

@@ -30,24 +40,59 @@

It's also possible to reset 'Backoff' instance. Once reset, a 'Backoff'
instance can be reused. On reset, the 'reset' event will be emitted.
The previous example would print:
```js
var Backoff = require('backoff');
```
1 10ms
2 20ms
3 40ms
4 80ms
5 160ms
6 320ms
7 640ms
8 1000ms
9 1000ms
10 1000ms
```
var backoff = new Backoff();
## API
backoff.on('backoff', function(number, delay) {
backoff.backoff();
});
### new Backoff([options])
backoff.on('reset', function() {
console.log('reset');
});
Construct a new backoff object.
backoff.backoff();
`options` is an object with the following defaults:
setTimeout(function() {
backoff.reset();
}, 5000);
```js
options = {
initialTimeout: 100,
maxTimeout: 10000
};
```
With these values, the timeout delay will exponentially increase from 100ms to
1000ms.
### backoff.backoff()
Start a backoff operation, doubling the previous timeout.
Returns true on success and false if a backoff was already in progress.
### 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.
### Event: 'backoff'
- number: number of backoff since last reset
- delay: current backoff delay
Emitted on backoff completion.
### 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/).

@@ -25,6 +25,5 @@ /*

"the '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,
maxTimeout: 1000
});

@@ -34,14 +33,10 @@ var spy = new sinon.spy();

var expectedDelays = [10, 20, 40, 80, 160, 320, 640, 1000];
for (var i = 0; i < expectedDelays.length; i++) {
backoff.backoff();
this.clock.tick(expectedDelays[i]);
test.ok(spy.calledWith(i + 1, expectedDelays[i]));
spy.reset();
}
backoff.backoff();
this.clock.tick(10);
test.ok(spy.calledOnce, 'backoff event has not been emitted');
test.done();
},
"the 'reset' event should be emitted on reset": function(test) {
"'reset' event should be emitted on reset": function(test) {
var backoff = new Backoff();

@@ -53,13 +48,114 @@ var reset = sinon.spy();

test.ok(reset.calledOnce);
test.ok(reset.calledOnce, 'reset event has not been emitted');
test.done();
},
"call to backoff should be ignored when a backoff is in progress": function(test) {
"the backoff delay should increase exponentially from initialTimeout to maxTimeout": function(test) {
var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 1000
});
var spy = new sinon.spy();
backoff.on('backoff', spy);
var clock = this.clock;
var delays = [10, 20, 40, 80, 160, 320, 640, 1000, 1000];
delays.forEach(function(delay, i) {
backoff.backoff();
clock.tick(delay);
});
delays.forEach(function(delay, i) {
test.equals(spy.getCall(i).args[0], i + 1);
test.equals(spy.getCall(i).args[1], delay);
});
test.done();
},
"the initial timeout should be greater than 0": function(test) {
test.throws(function() {
var backoff = new Backoff({
initialTimeout: -1
});
});
test.throws(function() {
var backoff = new Backoff({
initialTimeout: 0
});
});
test.doesNotThrow(function() {
var backoff = new Backoff({
initialTimeout: 1
});
});
test.done();
},
"the maximal timeout should be greater than 0": function(test) {
test.throws(function() {
var backoff = new Backoff({
maxTimeout: -1
});
});
test.throws(function() {
var backoff = new Backoff({
maxTimeout: 0
});
});
test.done();
},
"the maximal timeout should be greater than the original timeout": function(test) {
test.throws(function() {
var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 10
});
});
test.doesNotThrow(function() {
var backoff = new Backoff({
initialTimeout: 10,
maxTimeout: 11
});
});
test.done();
},
"call to backoff while a backoff is in progress should throw an error": function(test) {
var backoff = new Backoff();
test.ok(backoff.backoff() == true);
test.ok(backoff.backoff() == false);
backoff.backoff();
test.throws(function() {
backoff.backoff();
});
test.done();
},
"calling reset when a backoff is in progress should disarm the timeout": function(test) {
var backoff = new Backoff({
initialTimeout: 10
});
var spy = new sinon.spy();
backoff.on('backoff', spy);
backoff.backoff();
backoff.reset();
this.clock.tick(100); // 'backoff' should not be emitted.
test.equals(spy.callCount, 0, "backoff timeout did trigger");
test.done();
},
"it should be possible to reuse a backoff instance after reset": function(test) {

@@ -66,0 +162,0 @@ var backoff = new Backoff({

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