Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ milliseconds. If `options` is an array, a copy of that array is returned.
* `minTimeout`: The number of milliseconds before starting the first retry. Default is `1000`.
* `maxTimeout`: The maximum number of milliseconds between two retries. Default is `Infinity`.
* `randomize`: Randomizes the timeouts by multiplying with a factor between `1` to `2`. Default is `false`.
* `forever`: Whether the timeouts are for an operation that retries forever. If so and `retries` is `0`, one timeout is still returned, so there is a delay to repeat. Default is `false`.

The formula used to calculate the individual timeouts is:

Expand Down Expand Up @@ -186,7 +187,7 @@ Available options:

If `forever` is true, the following changes happen:
* `RetryOperation.errors()` will only output an array of one item: the last error.
* `RetryOperation` will repeatedly use the `timeouts` array. Once all of its timeouts have been used up, it restarts with the first timeout, then uses the second and so on.
* `RetryOperation` will keep retrying with the last timeout once all of the `timeouts` have been used up.

#### retryOperation.errors()

Expand All @@ -211,7 +212,7 @@ Defines the function `fn` that is to be retried and executes it for the first
time right away. The `fn` function can receive an optional `currentAttempt` callback that represents the number of attempts to execute `fn` so far.

Optionally defines `timeoutOps` which is an object having a property `timeout` in miliseconds and a property `cb` callback function.
Whenever your retry operation takes longer than `timeout` to execute, the timeout callback function `cb` is called.
Whenever your retry operation takes longer than `timeout` to execute, the timeout callback function `cb` is called with the current attempt number.


#### retryOperation.try(fn)
Expand Down
8 changes: 6 additions & 2 deletions lib/retry_operation.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ RetryOperation.prototype.retry = function(err) {
if (this._cachedTimeouts) {
// retry forever, only keep last error
this._errors.splice(0, this._errors.length - 1);
timeout = this._cachedTimeouts.slice(-1);
timeout = this._cachedTimeouts[this._cachedTimeouts.length - 1];
} else {
return false;
}
Expand Down Expand Up @@ -107,8 +107,12 @@ RetryOperation.prototype.attempt = function(fn, timeoutOps) {
var self = this;
if (this._operationTimeoutCb) {
this._timeout = setTimeout(function() {
self._operationTimeoutCb();
self._operationTimeoutCb(self._attempts);
}, self._operationTimeout);

if (this._options.unref) {
this._timeout.unref();
}
}

this._operationStart = new Date().getTime();
Expand Down
21 changes: 21 additions & 0 deletions test/integration/test-forever-timeout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
var common = require('../common');
var assert = common.assert;
var RetryOperation = require(common.dir.lib + '/retry_operation');

(function testForeverRepeatsLastTimeout() {
var operation = new RetryOperation([1, 2], {forever: true});
var originalSetTimeout = global.setTimeout;
var delays = [];
global.setTimeout = function(fn, delay) {
delays.push(delay);
return originalSetTimeout(function() {}, 0);
};

operation.attempt(function() {});
for (var i = 0; i < 4; i++) {
operation.retry(new Error('foo'));
}
global.setTimeout = originalSetTimeout;

assert.deepStrictEqual(delays, [1, 2, 2, 2]);
})();
32 changes: 32 additions & 0 deletions test/integration/test-operation-timeout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var common = require('../common');
var assert = common.assert;
var retry = require(common.dir.lib + '/retry');

(function testOperationTimeoutReceivesAttempts() {
var operation = retry.operation([1]);
var timedOutAttempts = [];

operation.attempt(function() {}, {
timeout: 1,
cb: function(attempts) {
timedOutAttempts.push(attempts);
operation.retry(new Error('timeout'));
}
});

process.on('exit', function() {
assert.deepStrictEqual(timedOutAttempts, [1, 2]);
});
})();

(function testOperationTimeoutIsUnrefed() {
var operation = retry.operation({unref: true});

operation.attempt(function() {}, {
timeout: 60 * 1000,
cb: function() {}
});

assert.strictEqual(operation._timeout.hasRef(), false);
operation.stop();
})();
Loading