Chore: add timeout to build

This commit is contained in:
SukkaW 2023-12-30 20:47:19 +08:00
parent a7c1b0fd17
commit a4458ee367
3 changed files with 57 additions and 30 deletions

View File

@ -9,6 +9,7 @@ import { task } from './lib/trace-runner';
import { fetchWithRetry } from './lib/fetch-retry';
import { SHARED_DESCRIPTION } from './lib/constants';
import { getGorhillPublicSuffixPromise } from './lib/get-gorhill-publicsuffix';
import picocolors from 'picocolors';
const s = new Sema(2);
@ -21,17 +22,12 @@ const querySpeedtestApi = async (keyword: string): Promise<Array<string | null>>
s.acquire()
]))[0];
let timer = null;
try {
const randomUserAgent = topUserAgents[Math.floor(Math.random() * topUserAgents.length)];
const key = `fetch speedtest endpoints: ${keyword}`;
console.log(key);
console.time(key);
// AbortSignal.timeout() is not supported by bun.
const controller = new AbortController();
timer = setTimeout(() => controller.abort(), 4000);
const res = await fetchWithRetry(`https://www.speedtest.net/api/js/servers?engine=js&search=${keyword}&limit=100`, {
headers: {
dnt: '1',
@ -39,21 +35,21 @@ const querySpeedtestApi = async (keyword: string): Promise<Array<string | null>>
accept: 'application/json, text/plain, */*',
'User-Agent': randomUserAgent,
'Accept-Language': 'en-US,en;q=0.9',
'Sec-Ch-Ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"',
'Sec-Ch-Ua-Mobile': '?0',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Sec-Gpc': '1'
...(randomUserAgent.includes('Chrome')
? {
'Sec-Ch-Ua-Mobile': '?0',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Sec-Gpc': '1'
}
: {})
},
signal: AbortSignal.timeout(1000 * 4),
retry: {
retryOnAborted: true
},
signal: controller.signal
retries: 2
}
});
if (!res.ok) {
throw new Error(`${res.statusText}\n${await res.text()}`);
}
const json = await res.json<Array<{ url: string }>>();
@ -64,9 +60,6 @@ const querySpeedtestApi = async (keyword: string): Promise<Array<string | null>>
console.log(e);
return [];
} finally {
if (timer) {
clearTimeout(timer);
}
s.release();
}
};
@ -116,16 +109,30 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async () => {
'.speedtest.leaptel.com.au',
'.speedtest.windstream.net',
'.speedtest.vodafone.com.au',
'.speedtest.rascom.ru',
'.speedtest.dchost.com',
'.speedtest.highnet.com',
'.speedtest.seattle.wa.limewave.net',
'.speedtest.optitel.com.au',
'.speednet.net.tr',
'.speedtest.angolacables.co.ao',
// Fast.com
'.fast.com',
// MacPaw
'speedtest.macpaw.com',
// speedtestmaster
'.netspeedtestmaster.com',
// Google Search Result of "speedtest", powered by this
'.measurement-lab.org',
// Google Fiber legacy speedtest site (new fiber speedtest use speedtestcustom.com)
'.speed.googlefiber.net'
'.speed.googlefiber.net',
// librespeed
'.backend.librespeed.org'
]);
const hostnameGroups = await Promise.all([
let timer;
const pMap = ([
'Hong Kong',
'Taiwan',
'China Telecom',
@ -154,15 +161,32 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async () => {
'Sydney',
'Brazil',
'Turkey'
].map(querySpeedtestApi));
for (const hostnames of hostnameGroups) {
if (Array.isArray(hostnames)) {
for (const hostname of hostnames) {
]).reduce<Record<string, Promise<void>>>((pMap, keyword) => {
pMap[keyword] = querySpeedtestApi(keyword).then(hostnameGroup => {
hostnameGroup.forEach(hostname => {
if (hostname) {
domains.add(hostname);
}
}
});
});
return pMap;
}, {});
try {
timer = setTimeout(() => {
console.error(picocolors.red('Task timeout!'));
Object.entries(pMap).forEach(([name, p]) => {
console.log(`[${name}]`, Bun.peek.status(p));
});
throw new Error('timeout');
}, 1000 * 60 * 2);
await Promise.all(Object.values(pMap));
} finally {
if (timer) {
clearTimeout(timer);
}
}

View File

@ -93,7 +93,6 @@ import type { TaskResult } from './lib/trace-runner';
buildStreamServicePromise,
buildMicrosoftCdnPromise,
buildSSPanelUIMAppProfilePromise,
downloadMockAssetsPromise
]);

View File

@ -7,7 +7,11 @@ class CustomAbortError extends Error {
}
const sleepWithAbort = (ms: number, signal: AbortSignal) => new Promise<void>((resolve, reject) => {
signal.throwIfAborted();
if (signal.aborted) {
reject(signal.reason);
return;
}
signal.addEventListener('abort', stop);
Bun.sleep(ms).then(done).catch(doReject);