Comparing version 2.3.0 to 2.4.0
# Changelog | ||
## 2.4.0 | ||
- Replace `FunctionCall.getResults` by `FunctionCall.getLastResult` to avoid | ||
storing intermediary results forever as this may lead to memory exhaustion | ||
when used in conjunction with an infinite number of backoffs. | ||
- Add `FunctionCall.getNumRetries` which returns the number of times the | ||
wrapped function was retried. | ||
## 2.3.0 | ||
@@ -4,0 +12,0 @@ |
@@ -30,3 +30,3 @@ #!/usr/bin/env node | ||
// Notice how the call is captured inside the closure. | ||
console.log('Retries: ' + call.getResults().length); | ||
console.log('Num retries: ' + call.getNumRetries()); | ||
@@ -33,0 +33,0 @@ if (err) { |
28
index.js
@@ -1,5 +0,3 @@ | ||
/* | ||
* Copyright (c) 2012 Mathieu Turcotte | ||
* Licensed under the MIT license. | ||
*/ | ||
// Copyright (c) 2012 Mathieu Turcotte | ||
// Licensed under the MIT license. | ||
@@ -16,8 +14,3 @@ var Backoff = require('./lib/backoff'); | ||
/** | ||
* Constructs a Fibonacci backoff. | ||
* @param options Fibonacci backoff strategy arguments. | ||
* @return The fibonacci backoff. | ||
* @see FibonacciBackoffStrategy | ||
*/ | ||
// Constructs a Fibonacci backoff. | ||
module.exports.fibonacci = function(options) { | ||
@@ -27,8 +20,3 @@ return new Backoff(new FibonacciBackoffStrategy(options)); | ||
/** | ||
* Constructs an exponential backoff. | ||
* @param options Exponential strategy arguments. | ||
* @return The exponential backoff. | ||
* @see ExponentialBackoffStrategy | ||
*/ | ||
// Constructs an exponential backoff. | ||
module.exports.exponential = function(options) { | ||
@@ -38,9 +26,3 @@ return new Backoff(new ExponentialBackoffStrategy(options)); | ||
/** | ||
* Constructs a FunctionCall for the given function and arguments. | ||
* @param fn The function to wrap in a backoff handler. | ||
* @param vargs The function's arguments (var args). | ||
* @param callback The function's callback. | ||
* @return The FunctionCall instance. | ||
*/ | ||
// Constructs a FunctionCall for the given function and arguments. | ||
module.exports.call = function(fn, vargs, callback) { | ||
@@ -47,0 +29,0 @@ var args = Array.prototype.slice.call(arguments); |
@@ -1,14 +0,10 @@ | ||
/* | ||
* Copyright (c) 2012 Mathieu Turcotte | ||
* Licensed under the MIT license. | ||
*/ | ||
// Copyright (c) 2012 Mathieu Turcotte | ||
// Licensed under the MIT license. | ||
var events = require('events'); | ||
var precond = require('precond'); | ||
var util = require('util'); | ||
/** | ||
* Backoff driver. | ||
* @param backoffStrategy Backoff delay generator/strategy. | ||
* @constructor | ||
*/ | ||
// A class to hold the state of a backoff operation. Accepts a backoff strategy | ||
// to generate the backoff delays. | ||
function Backoff(backoffStrategy) { | ||
@@ -29,12 +25,8 @@ events.EventEmitter.call(this); | ||
/** | ||
* Sets a limit, greater than 0, on the maximum number of backoffs. A 'fail' | ||
* event will be emitted when the limit is reached. | ||
* @param maxNumberOfRetry The maximum number of backoffs. | ||
*/ | ||
// Sets a limit, greater than 0, on the maximum number of backoffs. A 'fail' | ||
// event will be emitted when the limit is reached. | ||
Backoff.prototype.failAfter = function(maxNumberOfRetry) { | ||
if (maxNumberOfRetry < 1) { | ||
throw new Error('Maximum number of retry must be greater than 0. ' + | ||
'Actual: ' + maxNumberOfRetry); | ||
} | ||
precond.checkArgument(maxNumberOfRetry > 0, | ||
'Expected a maximum number of retry greater than 0 but got %s.', | ||
maxNumberOfRetry); | ||
@@ -44,11 +36,6 @@ this.maxNumberOfRetry_ = maxNumberOfRetry; | ||
/** | ||
* Starts a backoff operation. | ||
* @param err Optional paramater to let the listeners know why the backoff | ||
* operation was started. | ||
*/ | ||
// Starts a backoff operation. Accepts an optional parameter to let the | ||
// listeners know why the backoff operation was started. | ||
Backoff.prototype.backoff = function(err) { | ||
if (this.timeoutID_ !== -1) { | ||
throw new Error('Backoff in progress.'); | ||
} | ||
precond.checkState(this.timeoutID_ === -1, 'Backoff in progress.'); | ||
@@ -65,6 +52,3 @@ if (this.backoffNumber_ === this.maxNumberOfRetry_) { | ||
/** | ||
* Handles the backoff timeout completion. | ||
* @private | ||
*/ | ||
// Handles the backoff timeout completion. | ||
Backoff.prototype.onBackoff_ = function() { | ||
@@ -76,6 +60,3 @@ this.timeoutID_ = -1; | ||
/** | ||
* Stops any backoff operation and resets the backoff delay to its inital | ||
* value. | ||
*/ | ||
// Stops any backoff operation and resets the backoff delay to its inital value. | ||
Backoff.prototype.reset = function() { | ||
@@ -82,0 +63,0 @@ this.backoffNumber_ = 0; |
@@ -1,7 +0,6 @@ | ||
/* | ||
* Copyright (c) 2012 Mathieu Turcotte | ||
* Licensed under the MIT license. | ||
*/ | ||
// Copyright (c) 2012 Mathieu Turcotte | ||
// Licensed under the MIT license. | ||
var events = require('events'); | ||
var precond = require('precond'); | ||
var util = require('util'); | ||
@@ -12,35 +11,15 @@ | ||
/** | ||
* Returns true if the specified value is a function | ||
* @param val Variable to test. | ||
* @return Whether variable is a function. | ||
*/ | ||
function isFunction(val) { | ||
return typeof val == 'function'; | ||
} | ||
/** | ||
* Manages the calling of a function in a backoff loop. | ||
* @param fn Function to wrap in a backoff handler. | ||
* @param args Array of function's arguments. | ||
* @param callback Function's callback. | ||
* @constructor | ||
*/ | ||
// Wraps a function to be called in a backoff loop. | ||
function FunctionCall(fn, args, callback) { | ||
events.EventEmitter.call(this); | ||
if (!isFunction(fn)) { | ||
throw new Error('fn should be a function.' + | ||
'Actual: ' + typeof fn); | ||
} | ||
precond.checkIsFunction(fn, 'Expected fn to be a function.'); | ||
precond.checkIsArray(args, 'Expected args to be an array.'); | ||
precond.checkIsFunction(callback, 'Expected callback to be a function.'); | ||
if (!isFunction(callback)) { | ||
throw new Error('callback should be a function.' + | ||
'Actual: ' + typeof fn); | ||
} | ||
this.function_ = fn; | ||
this.arguments_ = args; | ||
this.callback_ = callback; | ||
this.results_ = []; | ||
this.lastResult_ = []; | ||
this.numRetries_ = 0; | ||
@@ -55,16 +34,16 @@ this.backoff_ = null; | ||
/** | ||
* Enum of states in which the FunctionCall can be. | ||
* @private | ||
*/ | ||
// States in which the call can be. | ||
FunctionCall.State_ = { | ||
// Call isn't started yet. | ||
PENDING: 0, | ||
// Call is in progress. | ||
RUNNING: 1, | ||
// Call completed successfully which means that either the wrapped function | ||
// returned successfully or the maximal number of backoffs was reached. | ||
COMPLETED: 2, | ||
// The call was aborted. | ||
ABORTED: 3 | ||
}; | ||
/** | ||
* @return Whether the call is pending. | ||
*/ | ||
// Checks whether the call is pending. | ||
FunctionCall.prototype.isPending = function() { | ||
@@ -74,5 +53,3 @@ return this.state_ == FunctionCall.State_.PENDING; | ||
/** | ||
* @return Whether the call is in progress. | ||
*/ | ||
// Checks whether the call is in progress. | ||
FunctionCall.prototype.isRunning = function() { | ||
@@ -82,5 +59,3 @@ return this.state_ == FunctionCall.State_.RUNNING; | ||
/** | ||
* @return Whether the call is completed. | ||
*/ | ||
// Checks whether the call is completed. | ||
FunctionCall.prototype.isCompleted = function() { | ||
@@ -90,5 +65,3 @@ return this.state_ == FunctionCall.State_.COMPLETED; | ||
/** | ||
* @return Whether the call is aborted. | ||
*/ | ||
// Checks whether the call is aborted. | ||
FunctionCall.prototype.isAborted = function() { | ||
@@ -98,44 +71,31 @@ return this.state_ == FunctionCall.State_.ABORTED; | ||
/** | ||
* Sets the backoff strategy. | ||
* @param strategy The backoff strategy to use. | ||
* @return Itself for chaining. | ||
*/ | ||
// Sets the backoff strategy to use. Can only be called before the call is | ||
// started otherwise an exception will be thrown. | ||
FunctionCall.prototype.setStrategy = function(strategy) { | ||
if (!this.isPending()) { | ||
throw new Error('FunctionCall in progress.'); | ||
} | ||
precond.checkState(this.isPending(), 'FunctionCall in progress.'); | ||
this.strategy_ = strategy; | ||
return this; | ||
return this; // Return this for chaining. | ||
}; | ||
/** | ||
* Returns all intermediary results returned by the wrapped function since | ||
* the initial call. | ||
* @return An array of intermediary results. | ||
*/ | ||
FunctionCall.prototype.getResults = function() { | ||
return this.results_.concat(); | ||
// Returns all intermediary results returned by the wrapped function since | ||
// the initial call. | ||
FunctionCall.prototype.getLastResult = function() { | ||
return this.lastResult_.concat(); | ||
}; | ||
/** | ||
* Sets the backoff limit. | ||
* @param maxNumberOfRetry The maximum number of backoffs. | ||
* @return Itself for chaining. | ||
*/ | ||
// Returns the number of times the wrapped function call was retried. | ||
FunctionCall.prototype.getNumRetries = function() { | ||
return this.numRetries_; | ||
}; | ||
// Sets the backoff limit. | ||
FunctionCall.prototype.failAfter = function(maxNumberOfRetry) { | ||
if (!this.isPending()) { | ||
throw new Error('FunctionCall in progress.'); | ||
} | ||
precond.checkState(this.isPending(), 'FunctionCall in progress.'); | ||
this.failAfter_ = maxNumberOfRetry; | ||
return this; | ||
return this; // Return this for chaining. | ||
}; | ||
/** | ||
* Aborts the call. | ||
*/ | ||
// Aborts the call. | ||
FunctionCall.prototype.abort = function() { | ||
if (this.isCompleted()) { | ||
throw new Error('FunctionCall already completed.'); | ||
} | ||
precond.checkState(!this.isCompleted(), 'FunctionCall already completed.'); | ||
@@ -149,13 +109,7 @@ if (this.isRunning()) { | ||
/** | ||
* Initiates the call to the wrapped function. | ||
* @param backoffFactory Optional factory function used to create the backoff | ||
* instance. | ||
*/ | ||
// Initiates the call to the wrapped function. Accepts an optional factory | ||
// function used to create the backoff instance; used when testing. | ||
FunctionCall.prototype.start = function(backoffFactory) { | ||
if (this.isAborted()) { | ||
throw new Error('FunctionCall aborted.'); | ||
} else if (!this.isPending()) { | ||
throw new Error('FunctionCall already started.'); | ||
} | ||
precond.checkState(!this.isAborted(), 'FunctionCall aborted.'); | ||
precond.checkState(this.isPending(), 'FunctionCall already started.'); | ||
@@ -168,3 +122,3 @@ var strategy = this.strategy_ || new FibonacciBackoffStrategy(); | ||
this.backoff_.on('ready', this.doCall_.bind(this)); | ||
this.backoff_.on('ready', this.doCall_.bind(this, true /* isRetry */)); | ||
this.backoff_.on('fail', this.doCallback_.bind(this)); | ||
@@ -178,10 +132,10 @@ this.backoff_.on('backoff', this.handleBackoff_.bind(this)); | ||
this.state_ = FunctionCall.State_.RUNNING; | ||
this.doCall_(); | ||
this.doCall_(false /* isRetry */); | ||
}; | ||
/** | ||
* Calls the wrapped function. | ||
* @private | ||
*/ | ||
FunctionCall.prototype.doCall_ = function() { | ||
// Calls the wrapped function. | ||
FunctionCall.prototype.doCall_ = function(isRetry) { | ||
if (isRetry) { | ||
this.numRetries_++; | ||
} | ||
var eventArgs = ['call'].concat(this.arguments_); | ||
@@ -193,17 +147,10 @@ events.EventEmitter.prototype.emit.apply(this, eventArgs); | ||
/** | ||
* Calls the wrapped function's callback with the last result returned by the | ||
* wrapped function. | ||
* @private | ||
*/ | ||
// Calls the wrapped function's callback with the last result returned by the | ||
// wrapped function. | ||
FunctionCall.prototype.doCallback_ = function() { | ||
var args = this.results_[this.results_.length - 1]; | ||
this.callback_.apply(null, args); | ||
this.callback_.apply(null, this.lastResult_); | ||
}; | ||
/** | ||
* Handles wrapped function's completion. This method acts as a replacement | ||
* for the original callback function. | ||
* @private | ||
*/ | ||
// Handles wrapped function's completion. This method acts as a replacement | ||
// for the original callback function. | ||
FunctionCall.prototype.handleFunctionCallback_ = function() { | ||
@@ -215,3 +162,3 @@ if (this.isAborted()) { | ||
var args = Array.prototype.slice.call(arguments); | ||
this.results_.push(args); // Save callback arguments. | ||
this.lastResult_ = args; // Save last callback arguments. | ||
events.EventEmitter.prototype.emit.apply(this, ['callback'].concat(args)); | ||
@@ -227,9 +174,3 @@ | ||
/** | ||
* Handles backoff event. | ||
* @param number Backoff number. | ||
* @param delay Backoff delay. | ||
* @param err The error that caused the backoff. | ||
* @private | ||
*/ | ||
// Handles the backoff event by reemitting it. | ||
FunctionCall.prototype.handleBackoff_ = function(number, delay, err) { | ||
@@ -236,0 +177,0 @@ this.emit('backoff', number, delay, err); |
@@ -1,5 +0,3 @@ | ||
/* | ||
* Copyright (c) 2012 Mathieu Turcotte | ||
* Licensed under the MIT license. | ||
*/ | ||
// Copyright (c) 2012 Mathieu Turcotte | ||
// Licensed under the MIT license. | ||
@@ -10,6 +8,3 @@ var util = require('util'); | ||
/** | ||
* Exponential backoff strategy. | ||
* @extends BackoffStrategy | ||
*/ | ||
// Exponential backoff strategy. | ||
function ExponentialBackoffStrategy(options) { | ||
@@ -22,3 +17,2 @@ BackoffStrategy.call(this, options); | ||
/** @inheritDoc */ | ||
ExponentialBackoffStrategy.prototype.next_ = function() { | ||
@@ -30,3 +24,2 @@ this.backoffDelay_ = Math.min(this.nextBackoffDelay_, this.getMaxDelay()); | ||
/** @inheritDoc */ | ||
ExponentialBackoffStrategy.prototype.reset_ = function() { | ||
@@ -33,0 +26,0 @@ this.backoffDelay_ = 0; |
@@ -1,5 +0,3 @@ | ||
/* | ||
* Copyright (c) 2012 Mathieu Turcotte | ||
* Licensed under the MIT license. | ||
*/ | ||
// Copyright (c) 2012 Mathieu Turcotte | ||
// Licensed under the MIT license. | ||
@@ -10,6 +8,3 @@ var util = require('util'); | ||
/** | ||
* Fibonacci backoff strategy. | ||
* @extends BackoffStrategy | ||
*/ | ||
// Fibonacci backoff strategy. | ||
function FibonacciBackoffStrategy(options) { | ||
@@ -22,3 +17,2 @@ BackoffStrategy.call(this, options); | ||
/** @inheritDoc */ | ||
FibonacciBackoffStrategy.prototype.next_ = function() { | ||
@@ -31,3 +25,2 @@ var backoffDelay = Math.min(this.nextBackoffDelay_, this.getMaxDelay()); | ||
/** @inheritDoc */ | ||
FibonacciBackoffStrategy.prototype.reset_ = function() { | ||
@@ -34,0 +27,0 @@ this.nextBackoffDelay_ = this.getInitialDelay(); |
@@ -1,5 +0,3 @@ | ||
/* | ||
* Copyright (c) 2012 Mathieu Turcotte | ||
* Licensed under the MIT license. | ||
*/ | ||
// Copyright (c) 2012 Mathieu Turcotte | ||
// Licensed under the MIT license. | ||
@@ -13,11 +11,10 @@ var events = require('events'); | ||
/** | ||
* Abstract class defining the skeleton for all backoff strategies. | ||
* @param options Backoff strategy options. | ||
* @param options.randomisationFactor The randomisation factor, must be between | ||
* 0 and 1. | ||
* @param options.initialDelay The backoff initial delay, in milliseconds. | ||
* @param options.maxDelay The backoff maximal delay, in milliseconds. | ||
* @constructor | ||
*/ | ||
// Abstract class defining the skeleton for the backoff strategies. Accepts an | ||
// object holding the options for the backoff strategy: | ||
// | ||
// * `randomisationFactor`: The randomisation factor which must be between 0 | ||
// and 1 where 1 equates to a randomization factor of 100% and 0 to no | ||
// randomization. | ||
// * `initialDelay`: The backoff initial delay in milliseconds. | ||
// * `maxDelay`: The backoff maximal delay in milliseconds. | ||
function BackoffStrategy(options) { | ||
@@ -48,6 +45,3 @@ options = options || {}; | ||
/** | ||
* Retrieves the maximal backoff delay. | ||
* @return The maximal backoff delay, in milliseconds. | ||
*/ | ||
// Gets the maximal backoff delay. | ||
BackoffStrategy.prototype.getMaxDelay = function() { | ||
@@ -57,6 +51,3 @@ return this.maxDelay_; | ||
/** | ||
* Retrieves the initial backoff delay. | ||
* @return The initial backoff delay, in milliseconds. | ||
*/ | ||
// Gets the initial backoff delay. | ||
BackoffStrategy.prototype.getInitialDelay = function() { | ||
@@ -66,6 +57,4 @@ return this.initialDelay_; | ||
/** | ||
* Template method that computes the next backoff delay. | ||
* @return The backoff delay, in milliseconds. | ||
*/ | ||
// Template method that computes and returns the next backoff delay in | ||
// milliseconds. | ||
BackoffStrategy.prototype.next = function() { | ||
@@ -78,7 +67,4 @@ var backoffDelay = this.next_(); | ||
/** | ||
* Computes the next backoff delay. | ||
* @return The backoff delay, in milliseconds. | ||
* @protected | ||
*/ | ||
// Computes and returns the next backoff delay. Intended to be overridden by | ||
// subclasses. | ||
BackoffStrategy.prototype.next_ = function() { | ||
@@ -88,5 +74,3 @@ throw new Error('BackoffStrategy.next_() unimplemented.'); | ||
/** | ||
* Template method that resets the backoff delay to its initial value. | ||
*/ | ||
// Template method that resets the backoff delay to its initial value. | ||
BackoffStrategy.prototype.reset = function() { | ||
@@ -96,6 +80,4 @@ this.reset_(); | ||
/** | ||
* Resets the backoff delay to its initial value. | ||
* @protected | ||
*/ | ||
// Resets the backoff delay to its initial value. Intended to be overridden by | ||
// subclasses. | ||
BackoffStrategy.prototype.reset_ = function() { | ||
@@ -102,0 +84,0 @@ throw new Error('BackoffStrategy.reset_() unimplemented.'); |
{ | ||
"name": "backoff", | ||
"description": "Fibonacci and exponential backoffs.", | ||
"version": "2.3.0", | ||
"version": "2.4.0", | ||
"license": "MIT", | ||
@@ -12,9 +12,12 @@ "author": "Mathieu Turcotte <turcotte.mat@gmail.com>", | ||
}, | ||
"dependencies": { | ||
"precond": "0.2" | ||
}, | ||
"devDependencies": { | ||
"sinon": "1.7", | ||
"nodeunit": "0.8", | ||
"jshint": "2.0" | ||
"sinon": "1.10", | ||
"nodeunit": "0.9" | ||
}, | ||
"scripts": { | ||
"pretest": "node_modules/jshint/bin/jshint lib/ tests/ examples/ index.js", | ||
"docco" : "docco lib/*.js lib/strategy/* index.js", | ||
"pretest": "jshint lib/ tests/ examples/ index.js", | ||
"test": "node_modules/nodeunit/bin/nodeunit tests/" | ||
@@ -24,3 +27,7 @@ }, | ||
"node": ">= 0.6" | ||
} | ||
}, | ||
"file": [ | ||
"index.js", | ||
"lib" | ||
] | ||
} |
@@ -93,3 +93,3 @@ # Backoff for Node.js | ||
var call = backoff.call(get, 'https://duplika.ca/', function(err, res) { | ||
console.log('Retries: ' + call.getResults().length); | ||
console.log('Num retries: ' + call.getNumRetries()); | ||
@@ -296,17 +296,25 @@ if (err) { | ||
#### call.getResults() | ||
#### call.getLastResult() | ||
Retrieves all intermediary results returned by the wrapped function. This | ||
Retrieves the last intermediary result 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. | ||
Returns an array containing the results returned by the last wrapped function | ||
call. For example, to get the error code returned by the last call, one would | ||
do the following. | ||
``` js | ||
var results = call.getResults(); | ||
var error = results[1][0]; | ||
var results = call.getLastResult(); | ||
// The error code is the first parameter of the callback. | ||
var error = results[0]; | ||
``` | ||
#### call.getNumRetries() | ||
Returns the number of times the wrapped function call was retried. For a | ||
wrapped function that succeeded immediately, this would return 0. 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. | ||
#### call.start() | ||
@@ -322,5 +330,5 @@ | ||
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. | ||
The last result can be retrieved using `call.getLastResult()`. 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. | ||
@@ -347,4 +355,8 @@ #### Event: 'call' | ||
## Annotated source code | ||
The annotated source code can be found at [mathieuturcotte.github.io/node-backoff/docs](http://mathieuturcotte.github.io/node-backoff/docs/). | ||
## License | ||
This code is free to use under the terms of the [MIT license](http://mturcotte.mit-license.org/). |
@@ -111,3 +111,3 @@ /* | ||
backoff.failAfter(0); | ||
}, /must be greater than 0/); | ||
}, /greater than 0 but got 0/); | ||
test.done(); | ||
@@ -114,0 +114,0 @@ }, |
@@ -39,3 +39,3 @@ /* | ||
new FunctionCall(1, [], function() {}); | ||
}, /should be a function/); | ||
}, /Expected fn to be a function./); | ||
test.done(); | ||
@@ -47,3 +47,3 @@ }, | ||
new FunctionCall(function() {}, [], 3); | ||
}, /should be a function/); | ||
}, /Expected callback to be a function./); | ||
test.done(); | ||
@@ -53,3 +53,5 @@ }, | ||
"isPending should return false once the call is started": function(test) { | ||
this.wrappedFn.yields(new Error()).yields(null, 'Success!'); | ||
this.wrappedFn. | ||
onFirstCall().yields(new Error()). | ||
onSecondCall().yields(null, 'Success!'); | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
@@ -69,3 +71,5 @@ | ||
"isRunning should return true when call is in progress": function(test) { | ||
this.wrappedFn.yields(new Error()).yields(null, 'Success!'); | ||
this.wrappedFn. | ||
onFirstCall().yields(new Error()). | ||
onSecondCall().yields(null, 'Success!'); | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
@@ -85,3 +89,5 @@ | ||
"isCompleted should return true once the call completes": function(test) { | ||
this.wrappedFn.yields(new Error()).yields(null, 'Success!'); | ||
this.wrappedFn. | ||
onFirstCall().yields(new Error()). | ||
onSecondCall().yields(null, 'Success!'); | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
@@ -101,3 +107,5 @@ | ||
"isAborted should return true once the call is aborted": function(test) { | ||
this.wrappedFn.yields(new Error()).yields(null, 'Success!'); | ||
this.wrappedFn. | ||
onFirstCall().yields(new Error()). | ||
onSecondCall().yields(null, 'Success!'); | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
@@ -190,6 +198,7 @@ | ||
var call = new FunctionCall(this.wrappedFn, [1, 2, 3], this.callback); | ||
this.wrappedFn.yields(new Error()) | ||
.yields(new Error()) | ||
.yields(new Error()) | ||
.yields(null, 'Success!'); | ||
this.wrappedFn. | ||
onCall(0).yields(new Error()). | ||
onCall(1).yields(new Error()). | ||
onCall(2).yields(new Error()). | ||
onCall(3).yields(null, 'Success!'); | ||
@@ -242,3 +251,3 @@ call.start(this.backoffFactory); | ||
"getResults should return intermediary results": function(test) { | ||
"getLastResult should return the last intermediary result": function(test) { | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
@@ -251,2 +260,3 @@ this.wrappedFn.yields(1); | ||
this.backoff.emit('ready'); | ||
test.deepEqual([i], call.getLastResult()); | ||
} | ||
@@ -256,7 +266,28 @@ | ||
this.backoff.emit('ready'); | ||
test.deepEqual([null], call.getLastResult()); | ||
test.deepEqual([[1], [2], [3], [4], [null]], call.getResults()); | ||
test.done(); | ||
}, | ||
"getNumRetries should return the number of retries": function(test) { | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
this.wrappedFn.yields(1); | ||
call.start(this.backoffFactory); | ||
// The inital call doesn't count as a retry. | ||
test.equals(0, call.getNumRetries()); | ||
for (var i = 2; i < 5; i++) { | ||
this.wrappedFn.yields(i); | ||
this.backoff.emit('ready'); | ||
test.equals(i - 1, call.getNumRetries()); | ||
} | ||
this.wrappedFn.yields(null); | ||
this.backoff.emit('ready'); | ||
test.equals(4, call.getNumRetries()); | ||
test.done(); | ||
}, | ||
"wrapped function's errors should be propagated": function(test) { | ||
@@ -263,0 +294,0 @@ var call = new FunctionCall(this.wrappedFn, [1, 2, 3], this.callback); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
516036
2
48
1858
359
1
+ Addedprecond@0.2
+ Addedprecond@0.2.3(transitive)