Skip to content

Commit d4c28de

Browse files
authored
#1095 retry on network error (#22)
* #1095 added request retry on network error * #1095 ci node ver update * #1095 circleci 2.0 * #1095 circleci 2.0 * #1095 circleci 2.0 * #1095 circleci 2.0 * #1095 fixed deps * #1095 updated node version * #725 requests keep-alive * version fix * #725 minor fix
1 parent b891149 commit d4c28de

17 files changed

+257
-63
lines changed

lib/client.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
const _ = require('lodash');
2+
const { STRATEGIES } = require('./retryStrategies');
3+
14
module.exports = ElasticIO;
25

36
ElasticIO.API_DEFAULT_BASE_URL = 'https://api.elastic.io';
7+
ElasticIO.RETRY_STRATEGIES = STRATEGIES;
48

59
var resources = {
610
accounts: require('./resources/accounts'),
@@ -18,7 +22,7 @@ var resources = {
1822
users: require('./resources/users')
1923
};
2024

21-
function ElasticIO(user, password) {
25+
function ElasticIO(user, password, options = {}) {
2226
var self = this;
2327
var baseUri = process.env.ELASTICIO_API_URI || ElasticIO.API_DEFAULT_BASE_URL;
2428
baseUri = baseUri.replace(/\/+$/, '');
@@ -28,12 +32,13 @@ function ElasticIO(user, password) {
2832
basePath: baseUri
2933
};
3034

31-
prepareResources(self, resources);
35+
36+
prepareResources(self, resources, options);
3237

3338
return this;
3439
}
3540

36-
function prepareResources(container, resources) {
41+
function prepareResources(container, resources, options = {}) {
3742
var self = this;
3843

3944
for (var next in resources) {
@@ -44,6 +49,7 @@ function prepareResources(container, resources) {
4449
container[name] = {};
4550
prepareResources(container[name], value);
4651
} else {
52+
self.options = _.defaults(self.options || {}, options);
4753
container[name] = new resources[next](self);
4854
}
4955
}

lib/resource.js

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,19 @@
1-
const Q = require('q');
21
const util = require('util');
32
const httpRequest = require('requestretry');
43
const API_VERSION = 'v1';
4+
const _ = require('lodash');
5+
const {
6+
MAP: RETRY_STRATEGIES_MAP,
7+
STRATEGIES: { ON_HTTP_OR_NETWORK_ERROR }
8+
} = require('./retryStrategies');
59

610
module.exports = ApiResource;
711

12+
813
function ApiResource(client) {
914
this.client = client;
1015
}
1116

12-
ApiResource.prototype.request = function request(method, path) {
13-
var api = this.client._api;
14-
15-
var requestMethod = request[method];
16-
17-
function createRequestOptions() {
18-
var options = {
19-
url: util.format("%s/%s", api.basePath, path),
20-
json: true,
21-
auth: {
22-
username: api.user,
23-
password: api.password
24-
}
25-
};
26-
27-
return options;
28-
}
29-
30-
function prepareResponse(response, body) {
31-
console.log(response);
32-
}
33-
34-
return Q.nfcall(requestMethod, createRequestOptions())
35-
.spread(prepareResponse);
36-
};
37-
3817
var hasOwn = {}.hasOwnProperty;
3918

4019
ApiResource.extend = function extend(sub) {
@@ -61,11 +40,13 @@ ApiResource.extend = function extend(sub) {
6140
};
6241

6342
ApiResource.method = function method(spec) {
64-
var verb = spec.method || ApiResource.GET;
43+
const verb = spec.method || ApiResource.GET;
6544
async function sendRequest(...args) {
45+
const defaultOptions = this.client.options || {};
6646
var self = this;
6747
var api = self.client._api;
6848
var path = self.path || '';
49+
6950
function provideOptions() {
7051
if (!path) {
7152
throw new Error("A resource must define 'path'");
@@ -78,7 +59,7 @@ ApiResource.method = function method(spec) {
7859
path = interpolatePath(path, args);
7960
const [requestBody, options] = args;
8061

81-
return createRequestOptions(verb, api, path, requestBody, options);
62+
return createRequestOptions(verb, api, path, requestBody, _.defaults(options || {}, defaultOptions));
8263
}
8364

8465

@@ -125,18 +106,33 @@ ApiResource.method = function method(spec) {
125106
return path;
126107
}
127108

128-
function createRequestOptions(verb, api, path, body, { retryCount, retryDelay } = {}) {
109+
function createRequestOptions(
110+
verb,
111+
api,
112+
path,
113+
body,
114+
{
115+
retryCount,
116+
retryDelay,
117+
retryStrategy
118+
} = {}
119+
) {
120+
const defaultRetryStrategy = RETRY_STRATEGIES_MAP[ON_HTTP_OR_NETWORK_ERROR];
129121
var options = {
130122
url: util.format("%s/%s", api.basePath, path),
131123
method: verb,
132124
json: true,
125+
forever: true,
126+
headers: {
127+
Connection: 'Keep-Alive'
128+
},
133129
auth: {
134130
username: api.user,
135131
password: api.password
136132
},
137133
maxAttempts: retryCount || 3,
138134
retryDelay: retryDelay || 100,
139-
retryStrategy: httpRequest.RetryStrategies.NetworkError,
135+
retryStrategy: retryStrategy ? RETRY_STRATEGIES_MAP[retryStrategy] : defaultRetryStrategy,
140136
fullResponse: true
141137
};
142138

lib/retryStrategies.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const httpRequest = require('requestretry');
2+
const ON_NETWORK_ERROR = Symbol('ON_NETWORK_ERROR');
3+
const ON_HTTP_OR_NETWORK_ERROR = Symbol('ON_HTTP_OR_NETWORK_ERROR');
4+
const ON_HTTP_ERROR = Symbol('ON_HTTP_ERROR');
5+
6+
module.exports = {
7+
MAP: {
8+
[ON_NETWORK_ERROR]: httpRequest.RetryStrategies.NetworkError,
9+
[ON_HTTP_OR_NETWORK_ERROR]: httpRequest.RetryStrategies.HTTPOrNetworkError,
10+
[ON_HTTP_ERROR]: httpRequest.RetryStrategies.HTTPError
11+
},
12+
STRATEGIES: {
13+
ON_NETWORK_ERROR,
14+
ON_HTTP_OR_NETWORK_ERROR,
15+
ON_HTTP_ERROR
16+
}
17+
};

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "elasticio-rest-node",
33
"description": "elastic.io REST API client",
4-
"version": "1.2.1",
4+
"version": "1.2.3",
55
"author": "elastic.io GmbH <[email protected]>",
66
"engines": {
77
"node": ">=10.15.0"

spec/resources/accounts.spec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ describe('/accounts', function () {
2020
];
2121

2222
nock('https://api.elastic.io')
23+
.matchHeader('Connection', 'Keep-Alive')
2324
.get('/v1/accounts/')
2425
.basicAuth({
2526
user: 'root',
@@ -58,6 +59,7 @@ describe('/accounts', function () {
5859
};
5960

6061
nock('https://api.elastic.io')
62+
.matchHeader('Connection', 'Keep-Alive')
6163
.get('/v1/accounts/55083c567aea6f030000001a')
6264
.basicAuth({
6365
user: 'root',
@@ -101,6 +103,7 @@ describe('/accounts', function () {
101103
};
102104

103105
nock('https://api.elastic.io')
106+
.matchHeader('Connection', 'Keep-Alive')
104107
.put('/v1/accounts/55083c567aea6f030000001a', input)
105108
.basicAuth({
106109
user: 'root',
@@ -144,6 +147,7 @@ describe('/accounts', function () {
144147
};
145148

146149
nock('https://api.elastic.io')
150+
.matchHeader('Connection', 'Keep-Alive')
147151
.post('/v1/accounts/', input)
148152
.basicAuth({
149153
user: 'root',

0 commit comments

Comments
 (0)