From 5ea58f6a8d7711be15bb507f2d418ffe8a271006 Mon Sep 17 00:00:00 2001 From: im47cn <67424112+im47cn@users.noreply.github.com> Date: Sun, 12 Jul 2026 22:18:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(walkforward):=20SSE=20=E6=94=BE=E5=BC=83?= =?UTF-8?q?=E6=97=B6=E6=B8=85=20localStorage=20+=20JSON=20=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=A4=B1=E8=B4=A5=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 跨组件后续修复的 WF 侧 (优化器侧同款问题另起 PR): - stopWalkForward 延迟分支 + MAX_RECONNECT 超限退出漏清 localStorage, 导致刷新页面 tryReconnect 会重连到已放弃/未取消的任务。两处补 removeItem(RECONNECT_KEY/JOB_KEY_KEY)。 - walkforward_stream 的 params/overrides JSON 解析失败静默降级为 {}/None, 会让用户配置 丢失变成无声 bug。升级为 logger.warning (仍降级不崩流, 但可诊断)。 --- backend/app/api/backtest.py | 6 ++++++ frontend/src/lib/walkforwardTask.ts | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/backend/app/api/backtest.py b/backend/app/api/backtest.py index 96dfb4a..ad8364d 100644 --- a/backend/app/api/backtest.py +++ b/backend/app/api/backtest.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio import json +import logging import queue import threading from dataclasses import asdict @@ -21,6 +22,8 @@ from app.services.backtest import ( is_available, ) +logger = logging.getLogger(__name__) + router = APIRouter(prefix="/api/backtest", tags=["backtest"]) FACTOR_DEFAULT_DAYS = 180 @@ -840,10 +843,13 @@ async def walkforward_stream( try: base_params = json.loads(params) if params else {} except (json.JSONDecodeError, TypeError): + # 静默降级会让"用户配置丢失"变成无声 bug: 至少 warn 供诊断 (前端应传合法 JSON)。 + logger.warning("walkforward: params JSON 解析失败, 降级为空 params: %r", params) base_params = {} try: ov = json.loads(overrides) if overrides else None except (json.JSONDecodeError, TypeError): + logger.warning("walkforward: overrides JSON 解析失败, 降级为 None: %r", overrides) ov = None wf_cfg = WalkForwardConfig( strategy_id=strategy_id, diff --git a/frontend/src/lib/walkforwardTask.ts b/frontend/src/lib/walkforwardTask.ts index 4e26413..3b62979 100644 --- a/frontend/src/lib/walkforwardTask.ts +++ b/frontend/src/lib/walkforwardTask.ts @@ -178,6 +178,9 @@ function connectSSE(url: string): void { if (reconnectAttempts > MAX_RECONNECT) { es.close() eventSource = null + // 清 localStorage: 否则刷新页面 tryReconnect 会重连到这个已放弃的任务。 + localStorage.removeItem(RECONNECT_KEY) + localStorage.removeItem(JOB_KEY_KEY) current = { ...current, isPending: false, error: '连接中断, 重连多次失败' } emit() } @@ -238,7 +241,15 @@ export function stopWalkForward(): void { localStorage.removeItem(JOB_KEY_KEY) } else if (eventSource) { const es = eventSource - setTimeout(() => { if (es === eventSource) { es.close(); eventSource = null } }, 5000) + // job_key 始终没到手(job 事件未达): 5 秒后放弃并清 localStorage, 避免刷新重连到未取消任务。 + // (若期间 job 到达, job handler 已 postCancel+清storage 并置 eventSource=null, 下面条件不成立跳过) + setTimeout(() => { + if (es === eventSource) { + es.close(); eventSource = null + localStorage.removeItem(RECONNECT_KEY) + localStorage.removeItem(JOB_KEY_KEY) + } + }, 5000) } if (current?.isPending) { current = { ...current, isPending: false, error: '已取消' }