UNPKG

2.21 kBJavaScriptView Raw
1var RetryOperation = require('./retry_operation');
2
3exports.operation = function(options) {
4 var timeouts = exports.timeouts(options);
5 return new RetryOperation(timeouts, {
6 forever: options && options.forever,
7 unref: options && options.unref
8 });
9};
10
11exports.timeouts = function(options) {
12 if (options instanceof Array) {
13 return [].concat(options);
14 }
15
16 var opts = {
17 retries: 10,
18 factor: 2,
19 minTimeout: 1 * 1000,
20 maxTimeout: Infinity,
21 randomize: false
22 };
23 for (var key in options) {
24 opts[key] = options[key];
25 }
26
27 if (opts.minTimeout > opts.maxTimeout) {
28 throw new Error('minTimeout is greater than maxTimeout');
29 }
30
31 var timeouts = [];
32 for (var i = 0; i < opts.retries; i++) {
33 timeouts.push(this.createTimeout(i, opts));
34 }
35
36 if (options && options.forever && !timeouts.length) {
37 timeouts.push(this.createTimeout(i, opts));
38 }
39
40 // sort the array numerically ascending
41 timeouts.sort(function(a,b) {
42 return a - b;
43 });
44
45 return timeouts;
46};
47
48exports.createTimeout = function(attempt, opts) {
49 var random = (opts.randomize)
50 ? (Math.random() + 1)
51 : 1;
52
53 var timeout = Math.round(random * opts.minTimeout * Math.pow(opts.factor, attempt));
54 timeout = Math.min(timeout, opts.maxTimeout);
55
56 return timeout;
57};
58
59exports.wrap = function(obj, options, methods) {
60 if (options instanceof Array) {
61 methods = options;
62 options = null;
63 }
64
65 if (!methods) {
66 methods = [];
67 for (var key in obj) {
68 if (typeof obj[key] === 'function') {
69 methods.push(key);
70 }
71 }
72 }
73
74 for (var i = 0; i < methods.length; i++) {
75 var method = methods[i];
76 var original = obj[method];
77
78 obj[method] = function retryWrapper() {
79 var op = exports.operation(options);
80 var args = Array.prototype.slice.call(arguments);
81 var callback = args.pop();
82
83 args.push(function(err) {
84 if (op.retry(err)) {
85 return;
86 }
87 if (err) {
88 arguments[0] = op.mainError();
89 }
90 callback.apply(this, arguments);
91 });
92
93 op.attempt(function() {
94 original.apply(obj, args);
95 });
96 };
97 obj[method].options = options;
98 }
99};