srsly
v1.0.0
Published
Yet another async retry function
Downloads
1
Readme
srsly
srsly
is a small library for retrying asynchronous functions until
they succeed.
Features
- Works in node and the browser.
- Supports arbitrary (potentially asynchronous) retry strategies. Several composable limiting and backoff functions are included to cover most common use cases and make building more complex ones easier.
- Equal support for functions that accept node-style callbacks and functions that return promises, with conversion between the two.
- No dependencies unless you want promise output and your JS implementation doesn't have native support. In that case you can provide whatever ES6-compatible implementation you like (the tests use Bluebird).
Install
You can either npm install srsly
, or just download a copy of srsly.js.
In node, require("srsly")
returns a factory function. This function is
exposed in the browser as the srsly
global.
Examples
Node-style API
var retry = require("srsly")();
retry(myNodeStyleAsyncFunction,"extra","args",function(err, result) {
// In the default configuration, myNodeStyleAsyncFunction will be
// called until it completes successfully, so err should never be set.
});
Promise API
var retry = require("srsly")({ style: require("bluebird") });
retry(myPromiseReturningFunction,"extra","args")
.then(function(result) {
// This promise isn't resolved until one of the promises returned by
// calling myPromiseReturningFunction resolves successfully.
},function(err) {
// As in the node-style example, errors are retried indefinitely by
// default, so this branch should never be reached.
});
Slightly Fancier
var fs = require("fs");
var retry = require("srsly")({
output: require("bluebird"),
delay: "exponential",
fuzz: 2,
maxDelay: 10, // seconds
tries: 10
});
retry(fs.readFile,"/etc/shadow")
.then(function(secrets) {
console.log(secrets);
},function(err) {
console.error("Reading failed 10 times. Here is the last error:",err);
});
API
srsly([options: Object]): Function
Creates a new retry function. The following options are valid:
input
String | Function (Default:"node"
)Declares the API of functions retried by the new retry function.
If the value is
"node"
, then any retried functions are assumed to take a node-style callback as their final argument.If the value is
"promise"
or an ES6-compatible promise constructor, then retried functions are expected to return a promise.output
String | Function (Default:node
)Declares the API provided by the new retry function.
If the value is
"node"
, then the retry function will accept a node-style callback as its final argument.If the value is
"promise"
, then thePromise
global must be an ES6-compatible promise constructor. This constructor will be used to create new promises.If the value is an ES6-compatible promise constructor, then the retry function will use that constructor to return a promise.
style
String | FunctionSetting this option is shorthand for setting both
input
andoutput
to the same value. If provided,input
andoutput
take precedence over the value of this option.strategy
FunctionUse the specified retry strategy. See Strategies.
delay
String | Number | Array | Function (Default: none)Wait before each retry. This option is ignored if the
strategy
option is provided.If the value is
"exponential"
, the initial retry is delayed one second, and subsequent retries are delayed by twice as long as the previous delay.If the value is
"fibonacci"
, the initial retry is delayed by one second, and subsequent retries are delayed by the number of seconds represented by the corresponding value in the Fibonacci sequence.If the value is a number, it is the number of seconds to wait before each retry.
If the value is an array, the first element in the array represents the number of seconds to wait before the first retry, the second element represents the wait before the second retry, and so on. If more retries are needed than there are elements in the array, the last element is reused for the excess retries.
If the value is a function, it is a delay strategy. See Delay Strategies.
fuzz
Number | Array (Default: none)Delay each retry by a random amount. If
fuzz
is a number, the delay is[0,value)
seconds. Iffuzz
is an array, the first two elements are interpreted as[minimum, maximum]
, and the delay is between[minimum,maxmimum)
.This option is ignored if the
strategy
option is provided. If thedelay
option is provided, any random delay is in addition to that delay. If themaxDelay
option is provided, the combined delay is subject to the limit.maxDelay
Number (Default: none)The maximum delay between retries in seconds. This option is ignored if the
strategy
option is provided.tries
Number (Default: no maximum)The maximum number of tries before giving up.
Strategies
Strategies determine what to do when an operation fails. Strategies are functions that take four arguments: the number of tries so far, the last error received, a function that will trigger an immediate retry, and another function that will abort retrying with a given error.
srsly.delay(getDelay: Function): Function
Returns a strategy that waits before retrying. getDelay
is a Delay
Strategy function.
srsly.maxTries(n: Number, [strategy: Function]): Function
Returns a strategy that terminates retrying if n
tries have failed. If
fewer than n
tries have failed, maxTries
delegates to strategy
if
provided, otherwise it retries immediately.
Delay Strategies
Delay strategies are functions used by the delay
strategy. The only
argument they require is the number of tries. They return a number
representing the number of seconds to wait before the next try.
srsly.specifiedDelays(delays: Array[Number]): Function
Returns a delay strategy that yields the elements of delays
. If the
number of tries is greater than the number of elements in delays
, the
last element is used for the excess tries.
srsly.exponentialDelays(base: Number = 1, multiplier: Number = 2): Function
Returns a delay strategy that yields exponentially increasing numbers.
For the first try, the number returned is base
. For each subsequent
try, base
is multiplied by multiplier
.
srsly.fibonacciDelays(start: Number = 1): Function
Returns a delay strategy that yields the numbers from the Fibonacci
sequence. If start
is provided and greater than 1, it is used as the
initial element of a new sequence constructed by the same process as the
Fibonacci sequence.
srsly.randomDelays(range: Number | Array = 1, [getDelay: Function]): Function
Returns a delay strategy that yields a random delay. If range
is a
number, the value returned will be between [0,value)
. If range
is an
array, the first two elements are interpreted as [minimum, maximum]
,
and the resulting value is in the range [minimum,maximum)
.
If getDelay
exists, any delay it yields is added to the random delay.
srsly.maxDelay(max: Number, getDelay: Function): Function
Returns a delay strategy that yields delays provided by getDelay
. If
any of these delays are larger than max
, max
is returned instead.