From f99d5f188fd937ba2e8769fed1c957f826a5d7a5 Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Mon, 1 Jul 2024 19:11:01 +0300 Subject: [PATCH 1/7] fetch: retry on ECONNRESET --- lib/fetch.js | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/lib/fetch.js b/lib/fetch.js index 8da22a8df..f09e5d06b 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -76,24 +76,31 @@ function doFetch(fetch_func, h1_fetch_func, options) { .catch(error => { clearTimeout(timeoutTimerId); if (!options.disable_http2 && error.code && /^ERR_HTTP2/.test(error.code)) { + log(' -- doFetch http2 error', error.code, uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); + + } else if (!options.disable_http2 && error.code && error instanceof FetchError && error.code === 'ABORT_ERR') { + + // Special case, when shared session request aborted by htmlparser logic. + /** + * https://polldaddy.com/poll/7451882/?s=twitter + * https://app.everviz.com/show/O0Cy7Dyt + */ + log(' -- doFetch h2 aborted error', uri); + resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); + + } else if (!options.retry_onerror && error.code === 'ECONNRESET') { + + log(' -- doFetch ECONNRESET retry', error.code, uri); + resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {retry_onerror: true}))); + } else { - if (!options.disable_http2 && error.code && error instanceof FetchError && error.code === 'ABORT_ERR') { - // Special case, when shared session request aborted by htmlparser logic. - /** - * https://polldaddy.com/poll/7451882/?s=twitter - * https://app.everviz.com/show/O0Cy7Dyt - */ - log(' -- doFetch h2 aborted error', uri); - resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else { - if (error instanceof AbortError) { - // `AbortError` before `response` occurs only on timeout. - error = 'timeout'; - } - reject(error); + if (error instanceof AbortError) { + // `AbortError` before `response` occurs only on timeout. + error = 'timeout'; } + reject(error); } }); }); From 40bbdf5b0bc3b58f49fa4d75634d9c68d91bfe8d Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Tue, 2 Jul 2024 21:50:53 +0300 Subject: [PATCH 2/7] retry on errors list --- lib/fetch.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/fetch.js b/lib/fetch.js index f09e5d06b..e511d70f4 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -28,6 +28,20 @@ const fetchH1 = h1NoCache({ rejectUnauthorized: false // By default skip auth check for all. }).fetch; +const RETRY_ON_ERROR = [ + 'ECONNRESET', + 'EAI_AGAIN', + 'ECONNREFUSED', + 'ENETUNREACH', + 'HPE_INVALID_HEADER_TOKEN', + 'HPE_INVALID_CONSTANT', + 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE', + 'ERR_SSL_UNSUPPORTED_PROTOCOL', + 'ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR', + 'ERR_SSL_UNSAFE_LEGACY_REGENERATION_DISABLED', + 'ERR_SSL_WRONG_VERSION_NUMBER' +]; + function doFetch(fetch_func, h1_fetch_func, options) { const fetch_options = Object.assign({}, options); @@ -90,10 +104,10 @@ function doFetch(fetch_func, h1_fetch_func, options) { log(' -- doFetch h2 aborted error', uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else if (!options.retry_onerror && error.code === 'ECONNRESET') { + } else if (!options.retry_onerror && RETRY_ON_ERROR.indexOf(error.code) > -1) { log(' -- doFetch ECONNRESET retry', error.code, uri); - resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {retry_onerror: true}))); + resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {retry_onerror: true, disable_http2: true}))); } else { if (error instanceof AbortError) { From 95ff6cfd0fab17a657bc35a211d15af40bca8e36 Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Tue, 2 Jul 2024 22:09:04 +0300 Subject: [PATCH 3/7] update algorythm --- lib/fetch.js | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/lib/fetch.js b/lib/fetch.js index e511d70f4..aff91d0ed 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -28,18 +28,12 @@ const fetchH1 = h1NoCache({ rejectUnauthorized: false // By default skip auth check for all. }).fetch; -const RETRY_ON_ERROR = [ - 'ECONNRESET', +const ERRORS_TO_RETRY = [ + 'ECONN', 'EAI_AGAIN', - 'ECONNREFUSED', - 'ENETUNREACH', - 'HPE_INVALID_HEADER_TOKEN', - 'HPE_INVALID_CONSTANT', - 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE', - 'ERR_SSL_UNSUPPORTED_PROTOCOL', - 'ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR', - 'ERR_SSL_UNSAFE_LEGACY_REGENERATION_DISABLED', - 'ERR_SSL_WRONG_VERSION_NUMBER' + 'ENET', + 'HPE_INVALID_', + 'ERR_SSL_' ]; function doFetch(fetch_func, h1_fetch_func, options) { @@ -104,10 +98,10 @@ function doFetch(fetch_func, h1_fetch_func, options) { log(' -- doFetch h2 aborted error', uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else if (!options.retry_onerror && RETRY_ON_ERROR.indexOf(error.code) > -1) { + } else if (!options.stopRecursion && ERRORS_TO_RETRY.some(code => code.indexOf(error.code) > -1)) { log(' -- doFetch ECONNRESET retry', error.code, uri); - resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {retry_onerror: true, disable_http2: true}))); + resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {stopRecursion: true, disable_http2: true}))); } else { if (error instanceof AbortError) { From 2969c7b9c639ecd6087fdfbc45848a895f003d10 Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Tue, 2 Jul 2024 22:14:55 +0300 Subject: [PATCH 4/7] bugfix --- lib/fetch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fetch.js b/lib/fetch.js index aff91d0ed..3f3fb72af 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -98,7 +98,7 @@ function doFetch(fetch_func, h1_fetch_func, options) { log(' -- doFetch h2 aborted error', uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else if (!options.stopRecursion && ERRORS_TO_RETRY.some(code => code.indexOf(error.code) > -1)) { + } else if (!options.stopRecursion && ERRORS_TO_RETRY.some(code => error.code.indexOf(code) > -1)) { log(' -- doFetch ECONNRESET retry', error.code, uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {stopRecursion: true, disable_http2: true}))); From 7d5061f9bf9b6871012f5ad49b23af3ba7b57376 Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Tue, 2 Jul 2024 22:21:03 +0300 Subject: [PATCH 5/7] bugfix undefined --- lib/fetch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fetch.js b/lib/fetch.js index 3f3fb72af..26e27e530 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -98,7 +98,7 @@ function doFetch(fetch_func, h1_fetch_func, options) { log(' -- doFetch h2 aborted error', uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else if (!options.stopRecursion && ERRORS_TO_RETRY.some(code => error.code.indexOf(code) > -1)) { + } else if (!options.stopRecursion && ERRORS_TO_RETRY.some(code => error.code?.indexOf(code) > -1)) { log(' -- doFetch ECONNRESET retry', error.code, uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {stopRecursion: true, disable_http2: true}))); From 0f8fa48b22501993e7eddb070fdca11095a7f36c Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Tue, 2 Jul 2024 22:35:13 +0300 Subject: [PATCH 6/7] CONFIG.ERRORS_TO_RETRY --- config.js | 10 +++++++++- lib/fetch.js | 10 +--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/config.js b/config.js index 0beaa8ac8..b6c8b5313 100644 --- a/config.js +++ b/config.js @@ -358,7 +358,15 @@ "twitter.status": {} }, - LOG_DATE_FORMAT: "\\[YY-MM-DD HH:mm:ss\\]:" + LOG_DATE_FORMAT: "\\[YY-MM-DD HH:mm:ss\\]:", + + ERRORS_TO_RETRY: [ + 'ECONN', + 'EAI_AGAIN', + 'ENET', + 'HPE_INVALID_', + 'ERR_SSL_' + ] }; // Providers config loader. diff --git a/lib/fetch.js b/lib/fetch.js index 26e27e530..a77ec5ebf 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -28,14 +28,6 @@ const fetchH1 = h1NoCache({ rejectUnauthorized: false // By default skip auth check for all. }).fetch; -const ERRORS_TO_RETRY = [ - 'ECONN', - 'EAI_AGAIN', - 'ENET', - 'HPE_INVALID_', - 'ERR_SSL_' -]; - function doFetch(fetch_func, h1_fetch_func, options) { const fetch_options = Object.assign({}, options); @@ -98,7 +90,7 @@ function doFetch(fetch_func, h1_fetch_func, options) { log(' -- doFetch h2 aborted error', uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else if (!options.stopRecursion && ERRORS_TO_RETRY.some(code => error.code?.indexOf(code) > -1)) { + } else if (!options.stopRecursion && CONFIG.ERRORS_TO_RETRY.some(code => error.code?.indexOf(code) > -1)) { log(' -- doFetch ECONNRESET retry', error.code, uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {stopRecursion: true, disable_http2: true}))); From 50224c8e47d57b732a3e9e26162a9c93d6cd8cd9 Mon Sep 17 00:00:00 2001 From: Nazar Leush Date: Tue, 2 Jul 2024 22:37:18 +0300 Subject: [PATCH 7/7] allow ERRORS_TO_RETRY == null --- lib/fetch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fetch.js b/lib/fetch.js index a77ec5ebf..67a362318 100644 --- a/lib/fetch.js +++ b/lib/fetch.js @@ -90,7 +90,7 @@ function doFetch(fetch_func, h1_fetch_func, options) { log(' -- doFetch h2 aborted error', uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {disable_http2: true}))); - } else if (!options.stopRecursion && CONFIG.ERRORS_TO_RETRY.some(code => error.code?.indexOf(code) > -1)) { + } else if (!options.stopRecursion && CONFIG.ERRORS_TO_RETRY?.some(code => error.code?.indexOf(code) > -1)) { log(' -- doFetch ECONNRESET retry', error.code, uri); resolve(doFetch(fetch_func, h1_fetch_func, Object.assign({}, options, {stopRecursion: true, disable_http2: true})));