Comparing version 2.4.1 to 2.5.0
@@ -28,2 +28,3 @@ // Copyright (c) 2012 Mathieu Turcotte | ||
this.failAfter_ = -1; | ||
this.retryPredicate_ = FunctionCall.DEFAULT_RETRY_PREDICATE_; | ||
@@ -47,2 +48,7 @@ this.state_ = FunctionCall.State_.PENDING; | ||
// The default retry predicate which considers any error as retriable. | ||
FunctionCall.DEFAULT_RETRY_PREDICATE_ = function(err) { | ||
return true; | ||
}; | ||
// Checks whether the call is pending. | ||
@@ -76,2 +82,12 @@ FunctionCall.prototype.isPending = function() { | ||
// Sets the predicate which will be used to determine whether the errors | ||
// returned from the wrapped function should be retried or not, e.g. a | ||
// network error would be retriable while a type error would stop the | ||
// function call. | ||
FunctionCall.prototype.retryIf = function(retryPredicate) { | ||
precond.checkState(this.isPending(), 'FunctionCall in progress.'); | ||
this.retryPredicate_ = retryPredicate; | ||
return this; | ||
}; | ||
// Returns all intermediary results returned by the wrapped function since | ||
@@ -97,3 +113,5 @@ // the initial call. | ||
FunctionCall.prototype.abort = function() { | ||
precond.checkState(!this.isCompleted(), 'FunctionCall already completed.'); | ||
if (this.isCompleted() || this.isAborted()) { | ||
return; | ||
} | ||
@@ -105,2 +123,5 @@ if (this.isRunning()) { | ||
this.state_ = FunctionCall.State_.ABORTED; | ||
this.lastResult_ = [new Error('Backoff aborted.')]; | ||
this.emit('abort'); | ||
this.doCallback_(); | ||
}; | ||
@@ -111,3 +132,3 @@ | ||
FunctionCall.prototype.start = function(backoffFactory) { | ||
precond.checkState(!this.isAborted(), 'FunctionCall aborted.'); | ||
precond.checkState(!this.isAborted(), 'FunctionCall is aborted.'); | ||
precond.checkState(this.isPending(), 'FunctionCall already started.'); | ||
@@ -161,4 +182,5 @@ | ||
if (args[0]) { | ||
this.backoff_.backoff(args[0]); | ||
var err = args[0]; | ||
if (err && this.retryPredicate_(err)) { | ||
this.backoff_.backoff(err); | ||
} else { | ||
@@ -165,0 +187,0 @@ this.state_ = FunctionCall.State_.COMPLETED; |
{ | ||
"name": "backoff", | ||
"description": "Fibonacci and exponential backoffs.", | ||
"version": "2.4.1", | ||
"version": "2.5.0", | ||
"license": "MIT", | ||
@@ -6,0 +6,0 @@ "author": "Mathieu Turcotte <turcotte.mat@gmail.com>", |
@@ -102,2 +102,3 @@ # Backoff for Node.js | ||
call.retryIf(function(err) { return err.status == 503; }); | ||
call.setStrategy(new backoff.ExponentialStrategy()); | ||
@@ -177,3 +178,3 @@ call.failAfter(10); | ||
An error will be thrown an error if a backoff operation is already in progress. | ||
An error will be thrown if a backoff operation is already in progress. | ||
@@ -307,10 +308,19 @@ In practice, this method should be called after a failed attempt to perform a | ||
#### call.retryIf(predicate) | ||
- predicate: a function which takes in as its argument the error returned | ||
by the wrapped function and determines whether it is retriable. | ||
Sets the predicate which will be invoked to determine whether a given error | ||
should be retried or not, e.g. a network error would be retriable while a type | ||
error would stop the function call. By default, all errors are considered to be | ||
retriable. | ||
This method should be called before `call.start()` otherwise an exception will | ||
be thrown. | ||
#### call.getLastResult() | ||
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 containing the arguments passed to the completion callback of | ||
the wrapped function. For example, to get the error code returned by the last | ||
Returns an array containing the last arguments passed to the completion callback | ||
of the wrapped function. For example, to get the error code returned by the last | ||
call, one would do the following. | ||
@@ -324,2 +334,5 @@ | ||
Note that if the call was aborted, it will contain the abort error and not the | ||
last error returned by the wrapped function. | ||
#### call.getNumRetries() | ||
@@ -337,11 +350,8 @@ | ||
#### call.abort() | ||
Aborts the call. | ||
Aborts the call and causes the completion callback to be invoked with an abort | ||
error if the call was pending or running; does nothing otherwise. This method | ||
can safely be called mutliple times. | ||
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. | ||
#### Event: 'call' | ||
@@ -367,2 +377,6 @@ | ||
#### Event: 'abort' | ||
Emitted when a call is aborted. | ||
## Annotated source code | ||
@@ -369,0 +383,0 @@ |
@@ -135,7 +135,7 @@ /* | ||
"failAfter should not be set by default": function(test) { | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
call.start(this.backoffFactory); | ||
test.equal(0, this.backoff.failAfter.callCount); | ||
test.done(); | ||
}, | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
call.start(this.backoffFactory); | ||
test.equal(0, this.backoff.failAfter.callCount); | ||
test.done(); | ||
}, | ||
@@ -232,2 +232,29 @@ "failAfter should be used as the maximum number of backoffs": function(test) { | ||
"call should fail when the retry predicate returns false": function(test) { | ||
var call = new FunctionCall(this.wrappedFn, [1, 2, 3], this.callback); | ||
call.retryIf(function(err) { return err.retriable; }); | ||
var retriableError = new Error(); | ||
retriableError.retriable = true; | ||
var fatalError = new Error(); | ||
fatalError.retriable = false; | ||
this.wrappedFn. | ||
onCall(0).yields(retriableError). | ||
onCall(1).yields(retriableError). | ||
onCall(2).yields(fatalError); | ||
call.start(this.backoffFactory); | ||
for (var i = 0; i < 2; i++) { | ||
this.backoff.emit('ready'); | ||
} | ||
test.equals(this.callback.callCount, 1); | ||
test.ok(this.callback.calledWith(fatalError)); | ||
test.ok(this.wrappedFn.alwaysCalledWith(1, 2, 3)); | ||
test.done(); | ||
}, | ||
"wrapped function's callback shouldn't be called after abort": function(test) { | ||
@@ -241,7 +268,26 @@ var call = new FunctionCall(function(callback) { | ||
test.equals(this.callback.callCount, 0, | ||
test.equals(this.callback.callCount, 1, | ||
'Wrapped function\'s callback shouldn\'t be called after abort.'); | ||
test.ok(this.callback.calledWithMatch(sinon.match(function (err) { | ||
return !!err.message.match(/Backoff aborted/); | ||
}, "abort error"))); | ||
test.done(); | ||
}, | ||
"abort event is emitted once when abort is called": function(test) { | ||
var call = new FunctionCall(this.wrappedFn, [], this.callback); | ||
this.wrappedFn.yields(new Error()); | ||
var callEventSpy = sinon.spy(); | ||
call.on('abort', callEventSpy); | ||
call.start(this.backoffFactory); | ||
call.abort(); | ||
call.abort(); | ||
call.abort(); | ||
test.equals(callEventSpy.callCount, 1); | ||
test.done(); | ||
}, | ||
"getLastResult should return the last intermediary result": function(test) { | ||
@@ -248,0 +294,0 @@ var call = new FunctionCall(this.wrappedFn, [], this.callback); |
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
57620
16
1050
383