From d83f8ccd04a1be0410bf6708dbf18f9eb4aeb353 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sun, 24 Dec 2023 16:44:26 +0800 Subject: [PATCH] Chore: add timeout on speedtest API fetching --- Build/build-speedtest-domainset.ts | 10 +++++++--- Build/lib/fetch-retry.ts | 28 +++++++++++++++++++--------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Build/build-speedtest-domainset.ts b/Build/build-speedtest-domainset.ts index 55a4172d..6e5a9595 100644 --- a/Build/build-speedtest-domainset.ts +++ b/Build/build-speedtest-domainset.ts @@ -13,7 +13,7 @@ import { getGorhillPublicSuffixPromise } from './lib/get-gorhill-publicsuffix'; const s = new Sema(3); const latestTopUserAgentsPromise = fetchWithRetry('https://unpkg.com/top-user-agents@latest/index.json') - .then(res => res.json() as Promise); + .then(res => res.json()); const querySpeedtestApi = async (keyword: string): Promise> => { const topUserAgents = (await Promise.all([ @@ -39,13 +39,17 @@ const querySpeedtestApi = async (keyword: string): Promise> 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Sec-Gpc': '1' - } + }, + retry: { + retryOnAborted: true + }, + signal: AbortSignal.timeout(4000) }); if (!res.ok) { throw new Error(`${res.statusText}\n${await res.text()}`); } - const json = await res.json() as Array<{ url: string }>; + const json = await res.json>(); s.release(); diff --git a/Build/lib/fetch-retry.ts b/Build/lib/fetch-retry.ts index bc042d09..2a822f6b 100644 --- a/Build/lib/fetch-retry.ts +++ b/Build/lib/fetch-retry.ts @@ -42,11 +42,16 @@ interface FetchRetryOpt { factor?: number, maxRetryAfter?: number, retry?: number, - onRetry?: (err: Error) => void + onRetry?: (err: Error) => void, + retryOnAborted?: boolean } -function createFetchRetry($fetch: typeof fetch): typeof fetch { - const fetchRetry = async (url: string | URL, opts: RequestInit & { retry?: FetchRetryOpt } = {}) => { +interface FetchWithRetry { + (url: string | URL | Request, opts?: RequestInit & { retry?: FetchRetryOpt }): Promise +} + +function createFetchRetry($fetch: typeof fetch): FetchWithRetry { + const fetchRetry: FetchWithRetry = async (url, opts = {}) => { const retryOpts = Object.assign( { // timeouts will be [10, 60, 360, 2160, 12960] @@ -54,13 +59,14 @@ function createFetchRetry($fetch: typeof fetch): typeof fetch { minTimeout: MIN_TIMEOUT, retries: MAX_RETRIES, factor: FACTOR, - maxRetryAfter: MAX_RETRY_AFTER + maxRetryAfter: MAX_RETRY_AFTER, + retryOnAborted: false }, opts.retry ); try { - return await retry(async (bail) => { + return await retry(async (bail) => { try { // this will be retried const res = (await $fetch(url, opts)) as Response; @@ -87,13 +93,17 @@ function createFetchRetry($fetch: typeof fetch): typeof fetch { err.name === 'AbortError' || ('digest' in err && err.digest === 'AbortError') ) { - console.log(picocolors.gray('[fetch abort]'), picocolors.gray(url.toString())); - return bail(err); + if (!retryOpts.retryOnAborted) { + console.log(picocolors.gray('[fetch abort]'), url); + return bail(err) as never; + } } } if (isClientError(err)) { - return bail(err); + return bail(err) as never; } + + console.log(picocolors.gray('[fetch fail]'), url); throw err; } }, retryOpts); @@ -110,7 +120,7 @@ function createFetchRetry($fetch: typeof fetch): typeof fetch { fetchRetry[key] = $fetch[key]; } - return fetchRetry as typeof fetch; + return fetchRetry; } export const defaultRequestInit: RequestInit = {