mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 19:04:15 +08:00
fix(optimizer): SSE 放弃时清 localStorage + JSON 解析失败告警
对抗式审查发现的两处健壮性问题 (与 walk-forward 同源, 此为优化器侧):
- stopOptimize 延迟分支 + MAX_RECONNECT 超限退出漏清 localStorage, 导致刷新页面
tryReconnect 会重连到已放弃/未取消的任务。两处补 removeItem(RECONNECT_KEY/JOB_KEY_KEY)。
- optimize_stream 的 params/overrides JSON 解析失败静默降级为 {}/None, 会让用户配置
丢失变成无声 bug。升级为 logger.warning (仍降级不崩流, 但可诊断)。
This commit is contained in:
@@ -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
|
||||
@@ -664,10 +667,13 @@ async def optimize_stream(
|
||||
try:
|
||||
base_params = json.loads(params) if params else {}
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
# 静默降级会让"用户配置丢失"变成无声 bug: 至少 warn 供诊断 (前端应传合法 JSON)。
|
||||
logger.warning("optimize: params JSON 解析失败, 降级为空 params: %r", params)
|
||||
base_params = {}
|
||||
try:
|
||||
ov = json.loads(overrides) if overrides else None
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
logger.warning("optimize: overrides JSON 解析失败, 降级为 None: %r", overrides)
|
||||
ov = None
|
||||
ocfg = OptimizeConfig(
|
||||
strategy_id=strategy_id,
|
||||
|
||||
@@ -174,6 +174,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()
|
||||
}
|
||||
@@ -244,9 +247,16 @@ export function stopOptimize(): void {
|
||||
localStorage.removeItem(RECONNECT_KEY)
|
||||
localStorage.removeItem(JOB_KEY_KEY)
|
||||
} else if (eventSource) {
|
||||
// 保持连接等 job 事件; 兜底: 5s 后仍没 key 就强关
|
||||
// 保持连接等 job 事件; 兜底: 5s 后仍没 key 就强关并清 localStorage,
|
||||
// 避免刷新重连到未取消任务。(若期间 job 到达, handler 已清并置 null, 下面条件不成立跳过)
|
||||
const es = eventSource
|
||||
setTimeout(() => { if (es === eventSource) { es.close(); eventSource = null } }, 5000)
|
||||
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: '已取消' }
|
||||
|
||||
Reference in New Issue
Block a user