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
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,23 @@ Returns `false` when no `error` value is given, or the maximum amount of retries
has been reached.

Otherwise it returns `true`, and retries the operation after the timeout for
the current attempt number.
the current attempt number. `retryOperation.nextTimeout()` tells you how long
that timeout is.

#### retryOperation.nextTimeout()

Returns the number of milliseconds the operation waits before the retry that the
last `retryOperation.retry()` call scheduled. Returns `null` if that call did not
schedule a retry, or if no retry has been scheduled since the operation was
created, `reset()` or `stop()`ped. Call it right after `retry()`: inside the next
attempt it still returns the timeout that led up to that attempt.

```javascript
if (operation.retry(err)) {
console.warn('Request failed, retrying in ' + operation.nextTimeout() + 'ms');
return;
}
```

#### retryOperation.stop()

Expand Down
13 changes: 12 additions & 1 deletion lib/retry_operation.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function RetryOperation(timeouts, options) {
this._timeout = null;
this._operationStart = null;
this._timer = null;
this._nextTimeout = null;

if (this._options.forever) {
this._cachedTimeouts = this._timeouts.slice(0);
Expand All @@ -26,6 +27,7 @@ module.exports = RetryOperation;
RetryOperation.prototype.reset = function() {
this._attempts = 1;
this._timeouts = this._originalTimeouts.slice(0);
this._nextTimeout = null;
}

RetryOperation.prototype.stop = function() {
Expand All @@ -38,13 +40,16 @@ RetryOperation.prototype.stop = function() {

this._timeouts = [];
this._cachedTimeouts = null;
this._nextTimeout = null;
};

RetryOperation.prototype.retry = function(err) {
if (this._timeout) {
clearTimeout(this._timeout);
}

this._nextTimeout = null;

if (!err) {
return false;
}
Expand All @@ -62,12 +67,14 @@ 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;
}
}

this._nextTimeout = timeout;

var self = this;
this._timer = setTimeout(function() {
self._attempts++;
Expand Down Expand Up @@ -136,6 +143,10 @@ RetryOperation.prototype.attempts = function() {
return this._attempts;
};

RetryOperation.prototype.nextTimeout = function() {
return this._nextTimeout;
};

RetryOperation.prototype.mainError = function() {
if (this._errors.length === 0) {
return null;
Expand Down
36 changes: 36 additions & 0 deletions test/integration/test-next-timeout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
var common = require('../common');
var assert = common.assert;
var retry = require(common.dir.lib + '/retry');

(function testNextTimeout() {
var operation = retry.operation([1, 2]);
var nextTimeouts = [];
assert.strictEqual(operation.nextTimeout(), null);

operation.attempt(function() {
operation.retry(new Error('foo'));
nextTimeouts.push(operation.nextTimeout());
});

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

(function testNextTimeoutWhenRetryingForever() {
var operation = retry.operation({retries: 1, minTimeout: 1, forever: true});
var nextTimeouts = [];

operation.attempt(function(attempt) {
operation.retry(new Error('foo'));
nextTimeouts.push(operation.nextTimeout());
if (attempt === 3) {
operation.stop();
nextTimeouts.push(operation.nextTimeout());
}
});

process.on('exit', function() {
assert.deepStrictEqual(nextTimeouts, [1, 1, 1, null]);
});
})();
Loading