From 4986e5c3c4c2a5630a442637a6aaff816cd5e523 Mon Sep 17 00:00:00 2001 From: claude_dev Date: Sat, 1 Aug 2026 13:52:46 +0800 Subject: [PATCH] =?UTF-8?q?feat(portfolio):=20=E7=BB=84=E5=90=88=E5=9B=9E?= =?UTF-8?q?=E6=B5=8B=E5=BC=82=E6=AD=A5=E5=8C=96(=E6=8E=A5=E5=85=A5=20orche?= =?UTF-8?q?strator=20task=20=E6=A1=86=E6=9E=B6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit routes_portfolio 同步 subprocess.run(timeout=600) >10min 回测被 504 杀。 改异步复用现有 sanguo_orchestrator:submit_portfolio 仿 submit_factor, 子进程执行搬至 portfolio_worker.py(三机自适应保留,timeout 600→3600), 复用 _wait_future/_on_done 持久化。前端 onSubmit 改 POST 拿 task_id → 轮询 /task/{id} → done 取 /portfolio/task/{id}/result。 - runner.py: + submit_portfolio + _portfolio_worker(lazy import) - portfolio_worker.py(新): 三机自适应 argv + 子进程 + stdout JSON → BacktestResult - routes_portfolio.py: POST async 返 task_id + GET /portfolio/task/{id}/result - 前端: postPortfolioBacktest 返 task_id + 轮询 status + 取 result(去 600s timeout) 不动策略逻辑/runner_backtest 核心/现有 task 接口。 --- frontend/src/api/portfolio.ts | 28 ++- .../src/views/backtest/PortfolioBacktest.vue | 36 +++- sanguo_api/routes_portfolio.py | 163 +++++----------- sanguo_orchestrator/portfolio_worker.py | 181 ++++++++++++++++++ sanguo_orchestrator/runner.py | 41 ++++ 5 files changed, 329 insertions(+), 120 deletions(-) create mode 100644 sanguo_orchestrator/portfolio_worker.py diff --git a/frontend/src/api/portfolio.ts b/frontend/src/api/portfolio.ts index 5215477..7cc18d5 100644 --- a/frontend/src/api/portfolio.ts +++ b/frontend/src/api/portfolio.ts @@ -58,11 +58,33 @@ export interface PortfolioBacktestResult { export async function postPortfolioBacktest( req: PortfolioBacktestReq, -): Promise { - const { data } = await apiClient.post( +): Promise { + const { data } = await apiClient.post<{ task_id: string }>( '/portfolio/backtest', req, - { timeout: 600000 }, + ) + return data.task_id +} + +export interface PortfolioTaskStatus { + task_id: string + status: string + stage: string + error_msg: string | null +} + +export async function getPortfolioTaskStatus( + taskId: string, +): Promise { + const { data } = await apiClient.get(`/task/${taskId}`) + return data +} + +export async function getPortfolioResult( + taskId: string, +): Promise { + const { data } = await apiClient.get( + `/portfolio/task/${taskId}/result`, ) return data } diff --git a/frontend/src/views/backtest/PortfolioBacktest.vue b/frontend/src/views/backtest/PortfolioBacktest.vue index 7bf89ec..3c1e26f 100644 --- a/frontend/src/views/backtest/PortfolioBacktest.vue +++ b/frontend/src/views/backtest/PortfolioBacktest.vue @@ -1,11 +1,13 @@