From 311a49110f68c450bf2fae9a6c9a87c440f3f379 Mon Sep 17 00:00:00 2001 From: wtx Date: Sat, 22 Aug 2026 05:09:52 +0800 Subject: [PATCH] fix: sync PPI scheduling and harden preflight --- apps/web/vue3/index.html | 19 +- apps/web/vue3/index_ml.html | 257 ++++++++++-------- apps/web/vue3/main.py | 19 ++ .../test_multilingual_ppi_scheduler_parity.py | 86 ++++++ tests/unit/test_ppi_owner_scheduling_task5.py | 160 ++++++++++- .../unit/test_string_snapshot_startup_warm.py | 33 +++ 6 files changed, 465 insertions(+), 109 deletions(-) create mode 100644 tests/unit/test_string_snapshot_startup_warm.py diff --git a/apps/web/vue3/index.html b/apps/web/vue3/index.html index 71a2efe5e..e5276e079 100644 --- a/apps/web/vue3/index.html +++ b/apps/web/vue3/index.html @@ -14188,10 +14188,25 @@ compare: [[flesh, peel]]`; }; }; + const fetchWithTransientRetry = async (input, init = {}) => { + const retryDelays = [500, 1500]; + for (let attempt = 0; ; attempt += 1) { + try { + return await fetch(input, init); + } catch (err) { + const message = String(err?.message || err || ''); + const transient = err instanceof TypeError + || /NetworkError|Failed to fetch|Load failed/i.test(message); + if (!transient || attempt >= retryDelays.length) throw err; + await new Promise(resolve => setTimeout(resolve, retryDelays[attempt])); + } + } + }; + const pollReferenceBundleDownloadTask = async (taskId, options = {}) => { const intervalMs = Number(options.intervalMs || 3000); while (true) { - const response = await fetch(`/api/task/${encodeURIComponent(taskId)}`); + const response = await fetchWithTransientRetry(`/api/task/${encodeURIComponent(taskId)}`); const data = await response.json().catch(() => ({})); if (!response.ok) { throw new Error(referenceBundleErrorMessage(data, `Reference species data status request failed (HTTP ${response.status})`)); @@ -14533,7 +14548,7 @@ compare: [[flesh, peel]]`; if (requestedStages.length === 1 && requestedStages[0] === 'ppi') { canonicalizePpiOwnerBiologicalScope(payload); } - const response = await fetch('/api/ppi/species-resolution', { + const response = await fetchWithTransientRetry('/api/ppi/species-resolution', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) diff --git a/apps/web/vue3/index_ml.html b/apps/web/vue3/index_ml.html index 78e922879..4acfb84e4 100644 --- a/apps/web/vue3/index_ml.html +++ b/apps/web/vue3/index_ml.html @@ -5033,7 +5033,7 @@ -
+
{{ t('基本参数') }}
@@ -6575,12 +6575,21 @@ RNA-seq KEGG/fgsea 会优先使用物种级 KEGG gene set;没有物种级缓
+ +