Abstraction for exponential and custom retry strategies for failed operations.
npm install retry
This module has been tested and is ready to be used.
The example below will retry a potentially failing dns.resolve
operation
10
times using an exponential backoff strategy. With the default settings, this
means the last attempt is made after 34 minutes and 7 seconds
.
var dns = require('dns');
var retry = require('retry');
function faultTolerantResolve(address, cb) {
var operation = retry.operation();
operation.attempt(function(currentAttempt) {
dns.resolve(address, function(err, addresses) {
if (operation.retry(err)) {
return;
}
cb(operation.mainError(), addresses);
});
});
}
faultTolerantResolve('nodejs.org', function(err, addresses) {
console.log(err, addresses);
});
Of course you can also configure the factors that go into the exponential backoff. See the API documentation below for all available settings. currentAttempt is an int representing the number of attempts so far.
var operation = retry.operation({
retries: 5,
factor: 3,
minTimeout: 1 * 1000,
maxTimeout: 60 * 1000,
randomize: true,
});
Creates a new RetryOperation
object. See the retry.timeouts()
function
below for available options
.
Returns an array of timeouts. All time options
and return values are in
milliseconds. If options
is an array, a copy of that array is returned.
options
is a JS object that can contain any of the following keys:
retries
: The maximum amount of times to retry the operation. Default is10
.factor
: The exponential factor to use. Default is2
.minTimeout
: The amount of time before starting the first retry. Default is1000
.maxTimeout
: The maximum amount of time between two retries. Default isInfinity
.randomize
: Randomizes the timeouts by multiplying with a factor between1
to2
. Default isfalse
.
The formula used to calculate the individual timeouts is:
var Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout);
Have a look at this article for a better explanation of approach.
If you want to tune your factor
/ times
settings to attempt the last retry
after a certain amount of time, you can use wolfram alpha. For example in order
to tune for 10
attempts in 5 minutes
, you can use this equation:
Explaining the various values from left to right:
k = 0 ... 9
: Theretries
value (10)1000
: TheminTimeout
value in ms (1000)x^k
: No need to change this,x
will be your resulting factor5 * 60 * 1000
: The desired total amount of time for retrying in ms (5 minutes)
To make this a little easier for you, use wolfram alpha to do the calculations:
http://www.wolframalpha.com/input/?i=Sum%5B1000x^k%2C+{k%2C+0%2C+9}%5D+%3D+5++60+*+1000
Creates a new RetryOperation
where timeouts
is an array where each value is
a timeout given in milliseconds.
Returns an array of all errors that have been passed to
retryOperation.retry()
so far.
A reference to the error object that occured most frequently. Errors are
compared using the error.message
property.
If multiple error messages occured the same amount of time, the last error object with that message is returned.
If no errors occured so far, the value is null
.
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.
This is an alias for retryOperation.attempt(fn)
. This is deprecated.
This is an alias for retryOperation.attempt(fn)
. This is deprecated.
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.
Returns an int representing the number of attempts it took to call fn
before it was successful.
retry is licensed under the MIT license.
#Changelog
0.4.0 Changed retryOperation.try() to retryOperation.attempt(). Deprecated the aliases start() and try() for it.
0.3.0 Added retryOperation.start() which is an alias for retryOperation.try().
0.2.0 Added attempts() function and parameter to retryOperation.try() representing the number of attempts it took to call fn().