feat(runtime): partial notify and diagnostics after scheduler timeout (#2338)

* feat(runtime): partial notify and diagnostics after scheduler timeout

After a hard timeout, scan already-saved analyses and enrich last_error
with completed/pending counts; optional push via DSA_TIMEOUT_PARTIAL_NOTIFY.

Refs #2328

* test(runtime): cover timeout partial delivery helpers

Refs #2328

* docs: document DSA_TIMEOUT_PARTIAL_NOTIFY

Refs #2328

* fix(config): use switch ui_control for timeout partial notify

DSA_TIMEOUT_PARTIAL_NOTIFY used ui_control=toggle, which SystemConfigResponse rejects and broke GET /config in backend-tests 1/3.

* docs(runtime): document timeout partial fail-open for operators

Channel exceptions are swallowed after the analysis lock is released, so they cannot keep status.running true. Collect/import failures stay in warning logs because last_error cannot distinguish them from zero completions.
This commit is contained in:
summer-meng
2026-09-13 17:18:52 +08:00
committed by GitHub
parent afca4fb732
commit 1168e31626
8 changed files with 905 additions and 2 deletions

View File

@@ -496,6 +496,7 @@ daily_stock_analysis/
| `SCHEDULE_TIME` | 定时执行时间 | `18:00` |
| `SCHEDULE_TIMES` | 多个定时执行时间,逗号分隔;为空时使用 `SCHEDULE_TIME` | 空 |
| `DSA_RUNTIME_SCHEDULER_TIMEOUT_SECONDS` | Web/API runtime scheduler 单次分析硬超时(秒,最小 60 秒);超时后终止独立分析进程,不阻塞后续任务 | `2700` |
| `DSA_TIMEOUT_PARTIAL_NOTIFY` | **默认开启(行为变化)**:硬超时后对已落库个股发送「部分完成」通知;此前超时不推送。`false` 时仍写入结构化 `last_error`,但不推送 | `true` |
| `LOG_DIR` | 日志目录 | `./logs` |
| `SAVE_CONTEXT_SNAPSHOT` | 保存分析历史 `context_snapshot`;设为 `false` 时新历史不保存 enhanced_context、market_phase_summary、AnalysisContextPack overview 或诊断快照,但不关闭当次 Prompt 低敏摘要 | `true` |
@@ -890,10 +891,13 @@ python main.py --schedule --no-run-immediately
| `SCHEDULE_TIME` | 每日执行时间 (HH:MM) | `18:00` | `09:30` |
| `SCHEDULE_TIMES` | 多个每日执行时间,逗号分隔;为空时使用 `SCHEDULE_TIME` | 空 | `09:20,12:30,15:10,18:00` |
| `DSA_RUNTIME_SCHEDULER_TIMEOUT_SECONDS` | Web/API runtime scheduler 单次分析硬超时(秒,最小 60 秒) | `2700` | `3600` |
| `DSA_TIMEOUT_PARTIAL_NOTIFY` | **默认开启(行为变化)**:硬超时后是否推送已落库个股的部分完成通知;此前超时不推送 | `true` | `false` |
| `SCHEDULE_RUN_IMMEDIATELY` | 定时模式启动时是否立即运行一次;未显式设置时沿用 `RUN_IMMEDIATELY` 的运行时覆盖语义 | `true` | `false` |
| `RUN_IMMEDIATELY` | 非定时模式启动时是否立即运行一次;同时作为未显式设置 `SCHEDULE_RUN_IMMEDIATELY` 时的 legacy 回退 | `true` | `false` |
| `TRADING_DAY_CHECK_ENABLED` | 交易日检查:非交易日跳过执行;设为 `false` 可强制执行 | `true` | `false` |
> 超时部分完成排障:通知渠道异常只记 warning`Partial timeout notification failed`)并跳过推送,**不抛出、不占用** `status().running`notify 在分析锁释放后的后台线程)。扫库 / `src.storage` 导入失败同样 fail-openAPI 上可能仍是 baseline `timed out after Ns`,或被 enrich 成 `completed=0`(与「确实没有落库」无法区分)。运维请搜 `Failed to collect completed analyses after timeout`、`Timeout partial delivery failed open`、`Partial timeout notification failed`。合入后首次发布请关注通知量,避免默认开启造成骚扰;可设 `DSA_TIMEOUT_PARTIAL_NOTIFY=false` 关闭推送。
例如在 Docker 中配置:
```bash