-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
97 lines (78 loc) · 2.12 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
92
93
94
95
96
97
'use strict';
var retry = require('retry');
var errorCodes = [
'EADDRINFO',
'ETIMEDOUT',
'ECONNRESET',
'ESOCKETTIMEDOUT',
'ENOTFOUND',
'EADDRNOTAVAIL'
];
function mixIn(dst, src) {
var key;
for (key in src) {
dst[key] = src[key];
}
return dst;
}
function requestReplay(request, options) {
var originalEmit = request.emit;
var operation;
var timeout;
var retrying = false;
var attempts = 0;
// Default options
options = mixIn({
errorCodes: errorCodes,
retries: 5,
factor: 2,
minTimeout: 2000,
maxTimeout: 35000,
randomize: true
}, options || {});
// Init retry
operation = retry.operation(options);
operation.attempt(function () {
retrying = false;
if (attempts) {
request.init();
request.start();
}
attempts++;
});
// Increase maxListeners because start() adds a new listener each time
request._maxListeners += options.retries + 1;
// Monkey patch emit to catch errors and retry
request.emit = function (name, error) {
// If name is replay, pass-through
if (name === 'replay') {
return originalEmit.apply(this, arguments);
}
// Do not emit anything if we are retrying
if (retrying) {
return;
}
// If not a retry error code, pass-through
if (name !== 'error' || options.errorCodes.indexOf(error.code) === -1) {
return originalEmit.apply(this, arguments);
}
timeout = operation._timeouts[0];
// Retry
if (operation.retry(error)) {
retrying = true;
request.abort();
request._aborted = false;
this.emit('replay', {
number: attempts - 1,
error: error,
delay: timeout
});
return 0;
}
// No more retries available, error out
error.replays = attempts - 1;
return originalEmit.apply(this, arguments);
};
return request;
}
module.exports = requestReplay;