forked from FGRibreau/node-request-retry
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
91 lines (74 loc) · 2.22 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
'use strict';
/*
* Request
*
* Copyright(c) 2014 Francois-Guillaume Ribreau <[email protected]>
* MIT Licensed
*
*/
var request = require('request');
var _ = require('fg-lodash');
var RetryStrategies = require('./strategies');
var DEFAULTS = {
maxAttempts: 5, // try 5 times
retryDelay: 5000, // wait for 5s before trying again
};
function Request(options, f, maxAttempts, retryDelay) {
this.maxAttempts = maxAttempts;
this.retryDelay = retryDelay;
this.attempts = 0;
/**
* Option object
* @type {Object}
*/
this.options = options;
/**
* Return true if the request should be retried
* @type {Function} (err, response) -> Boolean
*/
this.retryStrategy = _.isFunction(options.retryStrategy) ? options.retryStrategy : RetryStrategies.HTTPOrNetworkError;
this.f = _.once(f);
this._timeout = null;
this._req = null;
}
Request.request = request;
Request.prototype._tryUntilFail = function () {
this.maxAttempts--;
this.attempts++;
this._req = Request.request(this.options, function (err, response, body) {
if (response) {
response.attempts = this.attempts;
}
if (this.retryStrategy(err, response) && this.maxAttempts > 0) {
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.retryDelay);
return;
}
return this.f(err, response, body);
}.bind(this));
};
Request.prototype.abort = function () {
if (this._req) {
this._req.abort();
}
clearTimeout(this._timeout);
this.f(new Error('Aborted'));
};
// expose request methods from RequestRetry
['end', 'on', 'emit', 'once', 'setMaxListeners', 'start', 'removeListener', 'pipe', 'write'].forEach(function (methodName) {
Request.prototype[methodName] = makeGateway(methodName);
});
function makeGateway(methodName) {
return function () {
return this._req[methodName].apply(this._req, Array.prototype.slice.call(arguments));
};
}
function Factory(options, f) {
f = _.isFunction(f) ? f : _.noop;
var retry = _(options || {}).defaults(DEFAULTS).pick(Object.keys(DEFAULTS)).value();
var req = new Request(options, f, retry.maxAttempts, retry.retryDelay);
req._tryUntilFail();
return req;
}
module.exports = Factory;
Factory.Request = Request;
Factory.RetryStrategies = RetryStrategies;