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 1.1.0 to 1.2.0

examples/function_call.js

23

index.js

@@ -7,2 +7,3 @@ /*

var Backoff = require('./lib/backoff'),
FunctionCall = require('./lib/function_call.js'),
FibonacciBackoffStrategy = require('./lib/strategy/fibonacci'),

@@ -12,2 +13,3 @@ ExponentialBackoffStrategy = require('./lib/strategy/exponential');

module.exports.Backoff = Backoff;
module.exports.FunctionCall = FunctionCall;
module.exports.FibonacciStrategy = FibonacciBackoffStrategy;

@@ -19,2 +21,3 @@ module.exports.ExponentialStrategy = ExponentialBackoffStrategy;

* @param options Fibonacci backoff strategy arguments.
* @return The fibonacci backoff.
* @see FibonacciBackoffStrategy

@@ -29,2 +32,3 @@ */

* @param options Exponential strategy arguments.
* @return The exponential backoff.
* @see ExponentialBackoffStrategy

@@ -36,1 +40,20 @@ */

/**
* Calls a function in a backoff loop.
* @param fn Function to wrap in a backoff handler.
* @param vargs Function's arguments (var args).
* @param callback Function's callback.
* @return The call handle.
*/
module.exports.call = function(fn, vargs, callback) {
var args = Array.prototype.slice.call(arguments);
var call = new FunctionCall(args[0], args.slice(1, args.length - 1),
args[args.length - 1]);
process.nextTick(function() {
call.call();
});
return call;
};

4

package.json
{
"name": "backoff",
"description": "Fibonacci and exponential backoffs.",
"version": "1.1.0",
"version": "1.2.0",
"author": "Mathieu Turcotte <turcotte.mat@gmail.com>",

@@ -14,3 +14,3 @@ "keywords": ["backoff", "fibonacci", "exponential"],

"nodeunit": "0.7",
"jshint": "0.9"
"jshint": "0.9.0"
},

@@ -17,0 +17,0 @@ "scripts": {

@@ -19,2 +19,4 @@ # Backoff for Node.js [![Build Status](https://secure.travis-ci.org/MathieuTurcotte/node-backoff.png?branch=master)](http://travis-ci.org/MathieuTurcotte/node-backoff)

### Object Oriented
The usual way to instantiate a new `Backoff` object is to use one predefined

@@ -47,3 +49,5 @@ factory method: `backoff.fibonacci([options])`, `backoff.exponential([options])`.

// Do something when backoff ends, e.g. retry a failed
// operation (DNS lookup, API call, etc.).
// operation (DNS lookup, API call, etc.). If it fails
// again then backoff, otherwise reset the backoff
// instance.
fibonacciBackoff.backoff();

@@ -61,3 +65,3 @@ });

The previous example would print:
The previous example would print the following.

@@ -81,2 +85,24 @@ ```

### Functional
It's also possible to avoid some boilerplate code when invoking an asynchronous
function in a backoff loop by using `backoff.call(fn, args)`.
Typical usage looks like the following.
``` js
var call = backoff.call(get, 'https://duplika.ca/', function(err, res) {
console.log('Retries: ' + call.getResults().length);
if (err) {
console.log('Error: ' + err.message);
} else {
console.log('Status: ' + res.statusCode);
}
});
call.setStrategy(new backoff.ExponentialStrategy());
call.failAfter(10);
```
## API

@@ -88,3 +114,3 @@

See bellow for the options description.
See bellow for options description.

@@ -95,3 +121,3 @@ ### backoff.exponential([options])

The options are:
The options are the following.

@@ -106,2 +132,17 @@ - randomisationFactor: defaults to 0, must be between 0 and 1

### backoff.call(fn, [args, ...], callback)
- fn: function to call in a backoff handler
- args: function's arguments
- callback: function's callback accepting an error as its first argument
Calls an asynchronous function in a backoff handler so that it gets
automatically retried on error. The wrapped function will get retried until it
succeds or reach the maximum number of backoffs. In both cases, the callback
function will be invoked with the last results returned by the wrapped
function.
This function returns a `FunctionCall` instance that is going to be invoked on
next tick and can be used to configure and/or abort the call.
### Class Backoff

@@ -185,3 +226,3 @@

The options are:
The options are the following.

@@ -198,3 +239,3 @@ - randomisationFactor: defaults to 0, must be between 0 and 1

The options are:
The options are the following.

@@ -205,4 +246,81 @@ - randomisationFactor: defaults to 0, must be between 0 and 1

### Class FunctionCall
This class manages the calling of an asynchronous function within a backoff
loop.
This class should rarely be instantiated directly since the factory method
`backoff.call(fn, [args, ...], callback)` offers a more convenient and safer
way to create `FunctionCall` instances.
#### new FunctionCall(fn, args, callback)
- fn: asynchronous function to call
- args: an array containing fn's args
- callback: fn's callback
Constructs a function handler for the given asynchronous function.
#### call.setStrategy(strategy)
- strategy: strategy instance to use, defaults to `FibonacciStrategy`.
Sets the backoff strategy to use. This method should be called before
`call.call()`.
#### call.failAfter(maxNumberOfBackoffs)
- maxNumberOfBackoffs: maximum number of backoffs before the call is aborted
Sets the maximum number of backoffs before the call is aborted. This method
should be called before `call.call()`.
#### call.getResults()
Retrieves all intermediary results returned by the wrapped function. This
method can be called at any point in time during the call life cycle, i.e.
before, during and after the wrapped function invocation.
Returns an array of arrays containing the results returned by the wrapped
function for each call. For example, to get the error code returned by the
second call, one would do the following.
``` js
var results = call.getResults();
var error = results[1][0];
```
#### call.call()
Calls the wrapped function. This method should only be called once.
#### call.abort()
Aborts the call.
Past results can be retrieved using `call.getResults()`. This method can be
called at any point in time during the call life cycle, i.e. before, during
and after the wrapped function invocation.
#### Event: 'call'
- args: wrapped function's arguments
Emitted each time the wrapped function is called.
#### Event: 'callback'
- results: wrapped function's return values
Emitted each time the wrapped function invoke its callback.
#### Event: 'backoff'
- number: backoff number, starts at 0
- delay: backoff delay in milliseconds
Emitted each time a backoff operation is started.
## License
This code is free to use under the terms of the [MIT license](http://mturcotte.mit-license.org/).

@@ -32,3 +32,4 @@ /*

test.ok(spy.calledOnce);
test.ok(spy.calledOnce,
'Backoff event should be emitted when backoff starts.');
test.done();

@@ -46,3 +47,4 @@ },

test.ok(spy.calledOnce);
test.ok(spy.calledOnce,
'Ready event should be emitted when backoff ends.');
test.done();

@@ -59,3 +61,4 @@ },

test.equal(spy.getCall(0).args[1], 989);
test.equal(spy.getCall(0).args[1], 989, 'Backoff event should ' +
'carry the backoff delay as its second argument.');
test.done();

@@ -73,3 +76,4 @@ },

test.equal(spy.getCall(0).args[1], 989);
test.equal(spy.getCall(0).args[1], 989, 'Ready event should ' +
'carry the backoff delay as its second argument.');
test.done();

@@ -92,5 +96,5 @@ },

// Failure should occur on the third call, and not before.
test.ok(!spy.calledOnce);
test.ok(!spy.calledOnce, 'Fail event shouldn\'t have been emitted.');
this.backoff.backoff();
test.ok(spy.calledOnce);
test.ok(spy.calledOnce, 'Fail event should have been emitted.');

@@ -108,3 +112,3 @@ test.done();

backoff.backoff();
});
}, /in progress/);

@@ -118,3 +122,3 @@ test.done();

backoff.failAfter(0);
});
}, /must be greater than 0/);
test.done();

@@ -134,3 +138,3 @@ },

test.equals(spy.callCount, 0);
test.equals(spy.callCount, 0, 'Reset should have aborted the backoff.');
test.done();

@@ -141,3 +145,4 @@ },

this.backoff.reset();
test.ok(this.backoffStrategy.reset.calledOnce);
test.ok(this.backoffStrategy.reset.calledOnce,
'The backoff strategy should have been resetted.');
test.done();

@@ -155,3 +160,4 @@ },

test.ok(this.backoffStrategy.reset.calledOnce);
test.ok(this.backoffStrategy.reset.calledOnce,
'Backoff should have been resetted after failure.');
test.done();

@@ -162,16 +168,18 @@ },

this.backoffStrategy.next.returns(10);
var expectedNumbers = [0, 1, 2, 3, 4],
actualNumbers = [];
var spy = new sinon.spy();
this.backoff.on('backoff', spy);
for (var i = 0; i < 10; i++) {
for (var i = 0; i < expectedNumbers.length; i++) {
this.backoff.backoff();
this.clock.tick(10);
actualNumbers.push(spy.getCall(i).args[0]);
}
for (var j = 0; j < 10; j++) {
test.equals(spy.getCall(j).args[0], j);
}
test.deepEqual(expectedNumbers, actualNumbers,
'Backoff number should increase from 0 to N - 1.');
test.done();
}
};

@@ -21,9 +21,11 @@ /*

// Exponential sequence: x[i] = x[i-1] * 2.
var delays = [10, 20, 40, 80, 160, 320, 640, 1000, 1000];
var expectedDelays = [10, 20, 40, 80, 160, 320, 640, 1000, 1000];
var actualDelays = [];
delays.forEach(function(delay) {
var backoff = this.strategy.next();
test.equals(backoff, delay);
}, this);
for (var i = 0; i < expectedDelays.length; i++) {
actualDelays.push(this.strategy.next());
}
test.deepEqual(expectedDelays, actualDelays,
'Generated delays should follow an exponential sequence.');
test.done();

@@ -42,5 +44,6 @@ },

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

@@ -21,9 +21,11 @@ /*

// Fibonacci sequence: x[i] = x[i-1] + x[i-2].
var delays = [10, 10, 20, 30, 50, 80, 130, 210, 340, 550, 890, 1000];
var expectedDelays = [10, 10, 20, 30, 50, 80, 130, 210, 340, 550, 890, 1000];
var actualDelays = [];
delays.forEach(function(delay) {
var backoff = this.strategy.next();
test.equals(backoff, delay);
}, this);
for (var i = 0; i < expectedDelays.length; i++) {
actualDelays.push(this.strategy.next());
}
test.deepEqual(expectedDelays, actualDelays,
'Generated delays should follow a Fibonacci sequence.');
test.done();

@@ -42,5 +44,6 @@ },

var backoffDelay = strategy.next();
test.equals(backoffDelay, 10);
test.equals(backoffDelay, 10,
'Strategy should return the initial delay after reset.');
test.done();
}
};
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