Skip to content

Commit 40c99fb

Browse files
cyfung1031CodFrm
andauthored
🐛 新增批次检查脚本的 timeout, 避免一个脚本更新时间太长导致所有脚本检查失败 (#1265)
* 新增批次检查脚本的 timeout, 避免一个脚本更新时间太长导致所有脚本检查失败 * 🐛 修复批量更新超时机制的 4 个问题 - fetchScriptBody 添加 AbortSignal 支持 - 繁体转简体:確保次序 → 确保顺序 - 用 setTimeout+clearTimeout 替代 sleep,超时后正确清理 - 超时时通过 AbortController 中止进行中的请求 - Map 预初始化确保返回顺序一致 --------- Co-authored-by: 王一之 <[email protected]>
1 parent 2d24504 commit 40c99fb

File tree

2 files changed

+55
-15
lines changed

2 files changed

+55
-15
lines changed

src/app/service/service_worker/script.ts

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -772,17 +772,51 @@ export class ScriptService {
772772
setTimeout(resolve, Math.round(MIN_DELAY + ((++i / n + Math.random()) / 2) * (MAX_DELAY - MIN_DELAY)))
773773
);
774774

775-
return Promise.all(
776-
(uuids as string[]).map(async (uuid, _idx) => {
777-
const script = scripts[_idx];
778-
const res =
779-
!script || script.uuid !== uuid || !checkScripts.includes(script)
780-
? false
781-
: await this._checkUpdateAvailable(script, delayFn);
782-
if (!res) return false;
783-
return res;
784-
})
785-
);
775+
const CHECK_UPDATE_TIMEOUT_MS = 300_000; // 5 分钟超时
776+
777+
const results = new Map<
778+
string,
779+
| false
780+
| {
781+
updateAvailable: true;
782+
code: string;
783+
metadata: Partial<Record<string, string[]>>;
784+
}
785+
>();
786+
787+
// 预初始化 Map 确保顺序
788+
for (const uuid of uuids as string[]) {
789+
results.set(uuid, false);
790+
}
791+
792+
const abortController = new AbortController();
793+
let timeoutId: ReturnType<typeof setTimeout>;
794+
795+
const timeoutPromise = new Promise<void>((resolve) => {
796+
timeoutId = setTimeout(() => {
797+
abortController.abort();
798+
resolve();
799+
}, CHECK_UPDATE_TIMEOUT_MS);
800+
});
801+
802+
await Promise.race([
803+
timeoutPromise,
804+
Promise.allSettled(
805+
(uuids as string[]).map(async (uuid, _idx) => {
806+
const script = scripts[_idx];
807+
const res =
808+
!script || script.uuid !== uuid || !checkScripts.includes(script)
809+
? false
810+
: await this._checkUpdateAvailable(script, delayFn, abortController.signal);
811+
if (!res) return false;
812+
results.set(uuid, res);
813+
return res;
814+
})
815+
).finally(() => {
816+
clearTimeout(timeoutId);
817+
}),
818+
]);
819+
return [...results.values()];
786820
}
787821

788822
async _checkUpdateAvailable(
@@ -792,7 +826,8 @@ export class ScriptService {
792826
checkUpdateUrl?: string;
793827
metadata: Partial<Record<string, any>>;
794828
},
795-
delayFn?: () => Promise<any>
829+
delayFn?: () => Promise<any>,
830+
signal?: AbortSignal
796831
): Promise<false | { updateAvailable: true; code: string; metadata: SCMetadata }> {
797832
const { uuid, name, checkUpdateUrl } = script;
798833

@@ -804,8 +839,12 @@ export class ScriptService {
804839
name,
805840
});
806841
try {
807-
if (delayFn) await delayFn();
808-
const code = await fetchScriptBody(checkUpdateUrl);
842+
if (delayFn) {
843+
if (signal?.aborted) return false;
844+
await delayFn();
845+
}
846+
if (signal?.aborted) return false;
847+
const code = await fetchScriptBody(checkUpdateUrl, signal);
809848
const metadata = parseMetadata(code);
810849
if (!metadata) {
811850
logger.error("parse metadata failed");

src/pkg/utils/script.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ export function parseMetadata(code: string): SCMetadata | null {
4646
}
4747

4848
// 从网址取得脚本代码
49-
export async function fetchScriptBody(url: string): Promise<string> {
49+
export async function fetchScriptBody(url: string, signal?: AbortSignal): Promise<string> {
5050
const resp = await fetch(url, {
51+
signal,
5152
headers: {
5253
"Cache-Control": "no-cache",
5354
},

0 commit comments

Comments
 (0)