ソースを参照

Chore: add timeout to build

SukkaW 2 年 前
コミット
a4458ee367
3 ファイル変更57 行追加30 行削除
  1. 52 28
      Build/build-speedtest-domainset.ts
  2. 0 1
      Build/index.ts
  3. 5 1
      Build/lib/fetch-assets.ts

+ 52 - 28
Build/build-speedtest-domainset.ts

@@ -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);
     }
   }
 

+ 0 - 1
Build/index.ts

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

+ 5 - 1
Build/lib/fetch-assets.ts

@@ -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);