Projekt

Obecné

Profil

Stáhnout (8.76 KB) Statistiky
| Větev: | Revize:
1
<!-- badges/ -->
2
[![Build Status](https://secure.travis-ci.org/tim-kos/node-retry.png?branch=master)](http://travis-ci.org/tim-kos/node-retry "Check this project's build status on TravisCI")
3
[![codecov](https://codecov.io/gh/tim-kos/node-retry/branch/master/graph/badge.svg)](https://codecov.io/gh/tim-kos/node-retry)
4
<!-- /badges -->
5

    
6
# retry
7

    
8
Abstraction for exponential and custom retry strategies for failed operations.
9

    
10
## Installation
11

    
12
    npm install retry
13

    
14
## Current Status
15

    
16
This module has been tested and is ready to be used.
17

    
18
## Tutorial
19

    
20
The example below will retry a potentially failing `dns.resolve` operation
21
`10` times using an exponential backoff strategy. With the default settings, this
22
means the last attempt is made after `17 minutes and 3 seconds`.
23

    
24
``` javascript
25
var dns = require('dns');
26
var retry = require('retry');
27

    
28
function faultTolerantResolve(address, cb) {
29
  var operation = retry.operation();
30

    
31
  operation.attempt(function(currentAttempt) {
32
    dns.resolve(address, function(err, addresses) {
33
      if (operation.retry(err)) {
34
        return;
35
      }
36

    
37
      cb(err ? operation.mainError() : null, addresses);
38
    });
39
  });
40
}
41

    
42
faultTolerantResolve('nodejs.org', function(err, addresses) {
43
  console.log(err, addresses);
44
});
45
```
46

    
47
Of course you can also configure the factors that go into the exponential
48
backoff. See the API documentation below for all available settings.
49
currentAttempt is an int representing the number of attempts so far.
50

    
51
``` javascript
52
var operation = retry.operation({
53
  retries: 5,
54
  factor: 3,
55
  minTimeout: 1 * 1000,
56
  maxTimeout: 60 * 1000,
57
  randomize: true,
58
});
59
```
60

    
61
## API
62

    
63
### retry.operation([options])
64

    
65
Creates a new `RetryOperation` object. `options` is the same as `retry.timeouts()`'s `options`, with two additions:
66

    
67
* `forever`: Whether to retry forever, defaults to `false`.
68
* `unref`: Whether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`.
69
* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`.  
70

    
71
### retry.timeouts([options])
72

    
73
Returns an array of timeouts. All time `options` and return values are in
74
milliseconds. If `options` is an array, a copy of that array is returned.
75

    
76
`options` is a JS object that can contain any of the following keys:
77

    
78
* `retries`: The maximum amount of times to retry the operation. Default is `10`. Seting this to `1` means `do it once, then retry it once`.
79
* `factor`: The exponential factor to use. Default is `2`.
80
* `minTimeout`: The number of milliseconds before starting the first retry. Default is `1000`.
81
* `maxTimeout`: The maximum number of milliseconds between two retries. Default is `Infinity`.
82
* `randomize`: Randomizes the timeouts by multiplying with a factor between `1` to `2`. Default is `false`.
83

    
84
The formula used to calculate the individual timeouts is:
85

    
86
```
87
Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout)
88
```
89

    
90
Have a look at [this article][article] for a better explanation of approach.
91

    
92
If you want to tune your `factor` / `times` settings to attempt the last retry
93
after a certain amount of time, you can use wolfram alpha. For example in order
94
to tune for `10` attempts in `5 minutes`, you can use this equation:
95

    
96
![screenshot](https://github.com/tim-kos/node-retry/raw/master/equation.gif)
97

    
98
Explaining the various values from left to right:
99

    
100
* `k = 0 ... 9`:  The `retries` value (10)
101
* `1000`: The `minTimeout` value in ms (1000)
102
* `x^k`: No need to change this, `x` will be your resulting factor
103
* `5 * 60 * 1000`: The desired total amount of time for retrying in ms (5 minutes)
104

    
105
To make this a little easier for you, use wolfram alpha to do the calculations:
106

    
107
<http://www.wolframalpha.com/input/?i=Sum%5B1000*x^k%2C+{k%2C+0%2C+9}%5D+%3D+5+*+60+*+1000>
108

    
109
[article]: http://dthain.blogspot.com/2009/02/exponential-backoff-in-distributed.html
110

    
111
### retry.createTimeout(attempt, opts)
112

    
113
Returns a new `timeout` (integer in milliseconds) based on the given parameters.
114

    
115
`attempt` is an integer representing for which retry the timeout should be calculated. If your retry operation was executed 4 times you had one attempt and 3 retries. If you then want to calculate a new timeout, you should set `attempt` to 4 (attempts are zero-indexed).
116

    
117
`opts` can include `factor`, `minTimeout`, `randomize` (boolean) and `maxTimeout`. They are documented above.
118

    
119
`retry.createTimeout()` is used internally by `retry.timeouts()` and is public for you to be able to create your own timeouts for reinserting an item, see [issue #13](https://github.com/tim-kos/node-retry/issues/13).
120

    
121
### retry.wrap(obj, [options], [methodNames])
122

    
123
Wrap all functions of the `obj` with retry. Optionally you can pass operation options and
124
an array of method names which need to be wrapped.
125

    
126
```
127
retry.wrap(obj)
128

    
129
retry.wrap(obj, ['method1', 'method2'])
130

    
131
retry.wrap(obj, {retries: 3})
132

    
133
retry.wrap(obj, {retries: 3}, ['method1', 'method2'])
134
```
135
The `options` object can take any options that the usual call to `retry.operation` can take.
136

    
137
### new RetryOperation(timeouts, [options])
138

    
139
Creates a new `RetryOperation` where `timeouts` is an array where each value is
140
a timeout given in milliseconds.
141

    
142
Available options:
143
* `forever`: Whether to retry forever, defaults to `false`.
144
* `unref`: Wether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`.
145

    
146
If `forever` is true, the following changes happen:
147
* `RetryOperation.errors()` will only output an array of one item: the last error.
148
* `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.
149

    
150
#### retryOperation.errors()
151

    
152
Returns an array of all errors that have been passed to `retryOperation.retry()` so far. The
153
returning array has the errors ordered chronologically based on when they were passed to
154
`retryOperation.retry()`, which means the first passed error is at index zero and the last is
155
at the last index.
156

    
157
#### retryOperation.mainError()
158

    
159
A reference to the error object that occured most frequently. Errors are
160
compared using the `error.message` property.
161

    
162
If multiple error messages occured the same amount of time, the last error
163
object with that message is returned.
164

    
165
If no errors occured so far, the value is `null`.
166

    
167
#### retryOperation.attempt(fn, timeoutOps)
168

    
169
Defines the function `fn` that is to be retried and executes it for the first
170
time right away. The `fn` function can receive an optional `currentAttempt` callback that represents the number of attempts to execute `fn` so far.
171

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

    
175

    
176
#### retryOperation.try(fn)
177

    
178
This is an alias for `retryOperation.attempt(fn)`. This is deprecated. Please use `retryOperation.attempt(fn)` instead.
179

    
180
#### retryOperation.start(fn)
181

    
182
This is an alias for `retryOperation.attempt(fn)`. This is deprecated. Please use `retryOperation.attempt(fn)` instead.
183

    
184
#### retryOperation.retry(error)
185

    
186
Returns `false` when no `error` value is given, or the maximum amount of retries
187
has been reached.
188

    
189
Otherwise it returns `true`, and retries the operation after the timeout for
190
the current attempt number.
191

    
192
#### retryOperation.stop()
193

    
194
Allows you to stop the operation being retried. Useful for aborting the operation on a fatal error etc.
195

    
196
#### retryOperation.reset()
197

    
198
Resets the internal state of the operation object, so that you can call `attempt()` again as if this was a new operation object.
199

    
200
#### retryOperation.attempts()
201

    
202
Returns an int representing the number of attempts it took to call `fn` before it was successful.
203

    
204
## License
205

    
206
retry is licensed under the MIT license.
207

    
208

    
209
# Changelog
210

    
211
0.10.0 Adding `stop` functionality, thanks to @maxnachlinger.
212

    
213
0.9.0 Adding `unref` functionality, thanks to @satazor.
214

    
215
0.8.0 Implementing retry.wrap.
216

    
217
0.7.0 Some bug fixes and made retry.createTimeout() public. Fixed issues [#10](https://github.com/tim-kos/node-retry/issues/10), [#12](https://github.com/tim-kos/node-retry/issues/12), and [#13](https://github.com/tim-kos/node-retry/issues/13).
218

    
219
0.6.0 Introduced optional timeOps parameter for the attempt() function which is an object having a property timeout in milliseconds and a property cb callback function. Whenever your retry operation takes longer than timeout to execute, the timeout callback function cb is called.
220

    
221
0.5.0 Some minor refactoring.
222

    
223
0.4.0 Changed retryOperation.try() to retryOperation.attempt(). Deprecated the aliases start() and try() for it.
224

    
225
0.3.0 Added retryOperation.start() which is an alias for retryOperation.try().
226

    
227
0.2.0 Added attempts() function and parameter to retryOperation.try() representing the number of attempts it took to call fn().
(5-5/8)