Chore: add timeout on speedtest API fetching

This commit is contained in:
SukkaW 2023-12-24 16:44:26 +08:00
parent 5be5a4e0f6
commit d83f8ccd04
2 changed files with 26 additions and 12 deletions

View File

@ -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<string[]>);
.then(res => res.json<string[]>());
const querySpeedtestApi = async (keyword: string): Promise<Array<string | null>> => {
const topUserAgents = (await Promise.all([
@ -39,13 +39,17 @@ const querySpeedtestApi = async (keyword: string): Promise<Array<string | null>>
'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<Array<{ url: string }>>();
s.release();

View File

@ -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<Response>
}
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<Response>(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 = {