Skip to content

Commit 746284a

Browse files
committed
feat: support retry for socket hang up errors
1 parent 00fc9c3 commit 746284a

4 files changed

Lines changed: 78 additions & 37 deletions

File tree

.eslintrc.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ module.exports = {
1515
quotes: ['error', 'single'],
1616
semi: ['error', 'always'],
1717
},
18+
globals: {
19+
fetch: true,
20+
},
1821
};

packages/sdk-util/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
"wangshijun <shijun@arcblock.io> (https://ocap.arcblock.io)"
1515
],
1616
"dependencies": {
17-
"cross-fetch": "^4.1.0",
1817
"debug": "^4.3.4",
1918
"graphql": "16.5.0",
2019
"lodash.get": "^4.4.2",
2120
"lodash.isnull": "^3.0.0",
22-
"lodash.set": "^4.3.2"
21+
"lodash.set": "^4.3.2",
22+
"p-retry": "4"
2323
},
2424
"devDependencies": {
2525
"@babel/cli": "^7.22.9",

packages/sdk-util/src/index.js

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const fetch = require('cross-fetch');
1+
const pRetry = require('p-retry');
22
const set = require('lodash.set');
33
const get = require('lodash.get');
44
const { parse } = require('graphql/language/parser');
@@ -51,6 +51,38 @@ class BaseClient {
5151
if (this.config.enableMutation) {
5252
this.generateMutationFns(this.schema);
5353
}
54+
55+
this._doRequestWithRetry = (...args) =>
56+
pRetry(
57+
async () => {
58+
try {
59+
return await this._doRequest(...args);
60+
} catch (err) {
61+
// Only retry on "socket hang up"
62+
if (
63+
err &&
64+
typeof err.message === 'string' &&
65+
err.message.toLowerCase().includes('socket hang up')
66+
) {
67+
throw err;
68+
}
69+
throw new pRetry.AbortError(err);
70+
}
71+
},
72+
{
73+
retries: +this.config.retries ? +this.config.retries : 3,
74+
factor: 2,
75+
minTimeout: 100,
76+
maxTimeout: 1000,
77+
onFailedAttempt: err => {
78+
// eslint-disable-next-line no-console
79+
console.error(
80+
`GraphQL request attempt #${err.attemptNumber} failed, ${err.retriesLeft} retries left.`,
81+
err
82+
);
83+
},
84+
}
85+
);
5486
}
5587

5688
getQueries() {
@@ -75,7 +107,7 @@ class BaseClient {
75107
doRawQuery(query, requestOptions = {}, dataKey) {
76108
try {
77109
const cleanQuery = print(parse(query));
78-
return this._doRequest(cleanQuery, requestOptions, dataKey);
110+
return this._doRequestWithRetry(cleanQuery, requestOptions, dataKey);
79111
} catch (err) {
80112
throw new Error(`BaseClient: invalid raw query ${err.message || err.toString()}`);
81113
}
@@ -127,7 +159,7 @@ class BaseClient {
127159
set(base, 'definitions[0].directives', directives);
128160
set(base, 'definitions[0].selectionSet.selections', selections);
129161

130-
return this._doRequest(print(base), requestOptions);
162+
return this._doRequestWithRetry(print(base), requestOptions);
131163
}
132164

133165
generateQueryFns() {
@@ -146,7 +178,7 @@ class BaseClient {
146178
Object.keys(builders).forEach(key => {
147179
const queryFn = async (args, requestOptions = {}) => {
148180
const query = builders[key](this._sanitizeArgs(args), (requestOptions || {}).ignoreFields);
149-
const result = await this._doRequest(query, requestOptions, key);
181+
const result = await this._doRequestWithRetry(query, requestOptions, key);
150182
const pagedResult = this._getPagedResults({
151183
result,
152184
queryBuilder: builders[key],
@@ -237,7 +269,7 @@ class BaseClient {
237269
Object.keys(builders).forEach(key => {
238270
const mutationFn = async (args, requestOptions = {}) => {
239271
const query = builders[key](this._sanitizeArgs(args), (requestOptions || {}).ignoreFields);
240-
return this._doRequest(query, requestOptions, key);
272+
return this._doRequestWithRetry(query, requestOptions, key);
241273
};
242274

243275
mutationFn.type = 'mutation';
@@ -304,7 +336,7 @@ class BaseClient {
304336
message = `GraphQLError: ${message}`;
305337
}
306338

307-
const err = new Error(message);
339+
const err = res.status >= 500 ? new Error(message) : new pRetry.AbortError(message);
308340
err.errors = json.errors;
309341
err.status = res.status;
310342
throw err;
@@ -313,7 +345,7 @@ class BaseClient {
313345
// Handle HTTP errors
314346
if (res.status !== 200) {
315347
const message = json.error || json.message || `GraphQL Status Error ${res.status}`;
316-
const err = new Error(message);
348+
const err = res.status >= 500 ? new Error(message) : new pRetry.AbortError(message);
317349
err.status = res.status;
318350
err.response = json;
319351
throw err;
@@ -466,7 +498,7 @@ class BaseClient {
466498

467499
result.next = async () => {
468500
const query = queryBuilder(newArgs);
469-
const newResult = await this._doRequest(query, requestOptions, dataKey);
501+
const newResult = await this._doRequestWithRetry(query, requestOptions, dataKey);
470502
return this._getPagedResults({
471503
result: newResult,
472504
queryBuilder,

yarn.lock

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,11 @@
21242124
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
21252125
integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
21262126

2127+
"@types/retry@0.12.0":
2128+
version "0.12.0"
2129+
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
2130+
integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
2131+
21272132
"@types/stack-utils@^1.0.1":
21282133
version "1.0.1"
21292134
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -3636,13 +3641,6 @@ cross-fetch@^3.1.5:
36363641
dependencies:
36373642
node-fetch "^2.6.12"
36383643

3639-
cross-fetch@^4.1.0:
3640-
version "4.1.0"
3641-
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.1.0.tgz#8f69355007ee182e47fa692ecbaa37a52e43c3d2"
3642-
integrity sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==
3643-
dependencies:
3644-
node-fetch "^2.7.0"
3645-
36463644
cross-spawn@^5.0.1:
36473645
version "5.1.0"
36483646
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@@ -3767,11 +3765,11 @@ debug@^3.1.0:
37673765
ms "^2.1.1"
37683766

37693767
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4:
3770-
version "4.3.4"
3771-
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
3772-
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
3768+
version "4.4.1"
3769+
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
3770+
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
37733771
dependencies:
3774-
ms "2.1.2"
3772+
ms "^2.1.3"
37753773

37763774
debuglog@^1.0.1:
37773775
version "1.0.1"
@@ -4258,9 +4256,9 @@ esprima@^4.0.0, esprima@^4.0.1:
42584256
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
42594257

42604258
esquery@^1.0.1:
4261-
version "1.4.0"
4262-
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
4263-
integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
4259+
version "1.6.0"
4260+
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
4261+
integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
42644262
dependencies:
42654263
estraverse "^5.1.0"
42664264

@@ -5349,9 +5347,9 @@ import-fresh@^2.0.0:
53495347
resolve-from "^3.0.0"
53505348

53515349
import-fresh@^3.0.0:
5352-
version "3.3.0"
5353-
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
5354-
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
5350+
version "3.3.1"
5351+
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf"
5352+
integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==
53555353
dependencies:
53565354
parent-module "^1.0.0"
53575355
resolve-from "^4.0.0"
@@ -7273,12 +7271,7 @@ ms@2.0.0:
72737271
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
72747272
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
72757273

7276-
ms@2.1.2:
7277-
version "2.1.2"
7278-
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
7279-
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
7280-
7281-
ms@^2.0.0, ms@^2.1.1:
7274+
ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
72827275
version "2.1.3"
72837276
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
72847277
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -7391,7 +7384,7 @@ node-fetch-npm@^2.0.2:
73917384
json-parse-better-errors "^1.0.0"
73927385
safe-buffer "^5.1.1"
73937386

7394-
node-fetch@^2.5.0, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.7.0:
7387+
node-fetch@^2.5.0, node-fetch@^2.6.12, node-fetch@^2.6.7:
73957388
version "2.7.0"
73967389
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
73977390
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
@@ -7845,6 +7838,14 @@ p-reduce@^1.0.0:
78457838
resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
78467839
integrity sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==
78477840

7841+
p-retry@4:
7842+
version "4.6.2"
7843+
resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16"
7844+
integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==
7845+
dependencies:
7846+
"@types/retry" "0.12.0"
7847+
retry "^0.13.1"
7848+
78487849
p-try@^1.0.0:
78497850
version "1.0.0"
78507851
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
@@ -9646,6 +9647,11 @@ retry@^0.10.0:
96469647
resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
96479648
integrity sha512-ZXUSQYTHdl3uS7IuCehYfMzKyIDBNoAuUblvy5oGO5UJSUTmStUUVPXbA9Qxd173Bgre53yCQczQuHgRWAdvJQ==
96489649

9650+
retry@^0.13.1:
9651+
version "0.13.1"
9652+
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
9653+
integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
9654+
96499655
rimraf@2.6.3:
96509656
version "2.6.3"
96519657
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
@@ -11290,9 +11296,9 @@ wolfy87-eventemitter@^5.2.9:
1129011296
integrity sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==
1129111297

1129211298
word-wrap@~1.2.3:
11293-
version "1.2.3"
11294-
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
11295-
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
11299+
version "1.2.5"
11300+
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
11301+
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
1129611302

1129711303
wordwrap@^1.0.0:
1129811304
version "1.0.0"

0 commit comments

Comments
 (0)