Files
DCTS/docs/runbook-20260802-zombie-vortex-fix.md
fmq cd370d88e7 feat(all): 任务引擎双阶段解耦、僵尸涡旋修复、动态 CPU 配额与前端详情页重构
将 TLUSTY/SYNSPEC 拆为各自独立的 enabled/policy/strategies 阶段,
以策略链自动弹栈取代单级 seed_step 布尔回退;定向修复 2026-08-02
僵尸任务涡旋事故;新增节点并发配额热调;前端详情页从 1412 行巨型
视图拆为薄控制器 + detail 子模块,并补齐工具层与单测。

引擎与调度(task_engine_decoupling_design.md)
- models.rs: 新增 StagePolicy / EngineStageConfig / TaskSpec 阶段字段、
  normalize_compat() 校正旧版在途消息策略链、failed_stage 归因
- scheduler.rs: resolve_dispatchable_chain 派发门控、
  trigger_strategy_fallback 按 failed_stage 精确弹栈;启动期
  force_recompute/skip_converged(默认)/skip_failed 三策略
- db.rs: tasks 表 +7 列持久化阶段配置;终态守卫
  (mark_grid_point_running 仅 pending/queued→running;
  record_task_report 拒绝迟到失败翻黑 converged);策略弹栈快照

僵尸涡旋修复(runbook-20260802-zombie-vortex-fix.md)
- 全链路跨库活性交叉校验:派发/claim/孤儿回收/回退统一查 MQ 队列活性,
  活则放行、死则清僵尸,结构性消除"每点重复派发"
- stop/重启卫生:清队列同步 delete_tasks_by_ids,杜绝遗留 pending 行
- report_task: 幂等吸收 + 409 区分迟到冗余结果,仅 state_changed 时回退
- MQ: NULL workflow_name 回填 __legacy__、requeue 后迟到上报被 403 竞态修复

动态 CPU 配额(dynamic_cpu_slots_design.md)
- admin.rs: POST /admin/nodes/:id/quota(Option<Option<i32>> 区分
  缺字段/显式 null);nodes 表 +admin_max_slots
- worker.rs: effective_max_slots = min(admin, physical),心跳下发原子生效

科学产物保全(tlusty_result_artifacts.md)
- runner.rs: SYNSPEC 启动前快照 fort.12/fort.14 → .bfac/.emflux 防覆盖
- 半失败点(大气收敛+光谱失败)改判 Failed 并写入 note;仅 SYNSPEC
  场景不再恒判失败;撤销归档 LRU 200 上限改为永久保留
- executor.rs: 透传 synspec_params 数值参数(此前固定 None)

前端(dashboard/)
- workflowDetail.js 1412→328 行,拆出 views/detail/{ctx,overview,
  pointsTable,parSets,pointPanel}.js,AbortController 治理监听/请求生命周期
- 删除 wfActions.js,新增 wfEnginePanel.js(双阶段三维配置编辑面板)
- 新增 utils/{errors,format,icons,polling,yamlStage}.js 纯函数模块
- 路由级动态 import 代码分割;节点配额三点菜单 + Modal 管理
- 首次引入 node:test 单测(format/polling/yamlStage/psCache,644 行)
- 系统性补齐 a11y:skip-link、ARIA、Tab 键盘漫游、toast 关闭、退出动画

文档与工具
- 新增 6 篇设计/调研:引擎解耦、动态配额、涡旋 runbook、
  光谱正确性分析、收敛判断、产物归档
- PIPELINE/design/api/database 等协同重写为分布式 C/S 架构口径
- scripts/fetch_results.sh 跨节点产物备份;import_results 按 cno 升序导入
- workflows/sdB_cno.yaml: 新增 tlusty/synspec_stage 配置块,修正 wstart 笔误
2026-08-04 23:40:52 +08:00

113 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runbook:僵尸任务涡旋修复上线(2026-08-02)
## 背景
2026-08-01 晚重启工作流后发生重复派发涡旋(单点最高被算 101 次、wave3-9 积压饿死 6+ 小时)与收敛点被迟到失败报告翻黑(converged 净减少)。根因与修复见本次代码变更(三条不变量:每点至多一个活任务;converged 吸收态;stop/重启不产生僵尸)。
**当前生产状态(14:24 实时)**:工作流已暂停、槽位已排空、converged 4621 / failed 1139 / pending 3456。本 runbook 从"部署新版"开始。
## 第 1 步:部署新版服务端
```bash
cd /home/fmq/program/tlusty/tl208-s54/dcts # 本机(代码所在)
./scripts/deploy.sh -e remote -b compose -r server
```
部署期间工作流保持 paused,无影响。部署完成后确认容器正常:
```bash
ssh fmq@100.66.1.2 'cd /vol1/1000/program/dcts && docker compose ps server'
curl -s "http://100.66.1.2:8090/api/status" -H "Authorization: Bearer <admin_token>" | head -c 300
```
## 第 2 步:存量清理(维护窗口,约 2 分钟)
在 100.66.1.2 上执行。建议停容器避免 WAL 锁争用(节点心跳会短暂失败并自动恢复):
```bash
ssh fmq@100.66.1.2
cd /vol1/1000/program/dcts
docker compose stop server
# 确认队列库路径(compose 默认为 data/dcts_queue.db
ls -la data/dcts.db data/dcts_queue.db
# 备份
cp data/dcts.db data/dcts.db.bak.$(date +%s)
cp data/dcts_queue.db data/dcts_queue.db.bak.$(date +%s)
# 清理 + 修复(先审计后执行)
sqlite3 data/dcts.db <<'SQL'
ATTACH 'file:data/dcts_queue.db?mode=ro' AS q;
-- 审计 1:将删除的僵尸行数(预期数千条;= 无队列凭证的 pending 行)
SELECT COUNT(*) AS zombies FROM main.tasks
WHERE status='pending' AND workflow_name='sdB_cno'
AND task_id NOT IN (SELECT task_id FROM q.task_queue);
-- 审计 2:被翻黑的收敛点数(success_method 非空的 failed 点)
SELECT COUNT(*) AS flipped FROM grid_points
WHERE workflow_name='sdB_cno' AND status='failed' AND success_method IS NOT NULL;
-- 审计 3:从未真正获得种子救援的 failed 点数
SELECT COUNT(*) AS never_rescued FROM grid_points
WHERE workflow_name='sdB_cno' AND status='failed' AND success_method IS NULL
AND NOT EXISTS (SELECT 1 FROM tasks t
WHERE t.point_name=grid_points.name
AND t.workflow_name='sdB_cno'
AND t.task_type='seed_step');
-- 执行 1:清僵尸(claimed 在途行自动保留,NOT IN 子查询不过滤 status
DELETE FROM main.tasks
WHERE status='pending' AND workflow_name='sdB_cno'
AND task_id NOT IN (SELECT task_id FROM q.task_queue);
-- 执行 2:修复被翻黑的收敛点
UPDATE grid_points SET status='converged'
WHERE workflow_name='sdB_cno' AND status='failed' AND success_method IS NOT NULL;
-- 执行 3(可选):复活从未获救援的 failed 点,走正常 cold_run → 种子回退路径
UPDATE grid_points SET status='pending'
WHERE workflow_name='sdB_cno' AND status='failed' AND success_method IS NULL
AND NOT EXISTS (SELECT 1 FROM tasks t
WHERE t.point_name=grid_points.name
AND t.workflow_name=grid_points.workflow_name
AND t.task_type='seed_step');
SQL
docker compose up -d server
```
> 注意:执行 3 会把约百个点打回 pending,重启后它们会先跑一轮 cold_run 再触发种子回退——这是预期行为。
## 第 3 步:启动工作流
```bash
curl -s -X POST "http://100.66.1.2:8090/api/workflows/sdB_cno/start" \
-H "Authorization: Bearer <admin_token>"
```
启动时 `initialize_grid` 卫生逻辑会再清一遍残留(与第 2 步不冲突),随后 3456 个 pending 点按 wave 升序正常派发。
## 第 4 步:验证(启动后 1 小时内)
```bash
# 1. 无重复派发:最近 1 小时每个点应至多 1 个任务(预期空结果)
ssh fmq@100.66.1.2 "sqlite3 /vol1/1000/program/dcts/data/dcts.db \
\"SELECT point_name, COUNT(*) n FROM tasks WHERE created_at > datetime('now','-1 hour') GROUP BY point_name HAVING n > 1;\""
# 2. converged 单调不减、queued 以 ~100/h 下降(每 10 分钟看一次)
watch -n 600 "curl -s http://100.66.1.2:8090/api/status -H 'Authorization: Bearer <admin_token>' | head -c 200"
# 3. 历史涡旋点不再产生新任务
ssh fmq@100.66.1.2 "sqlite3 /vol1/1000/program/dcts/data/dcts.db \
\"SELECT COUNT(*) FROM tasks WHERE point_name='t55000_g5.0_he2_c-4_n-3_o-4' AND created_at > datetime('now','-1 hour');\""
# 4. 观察项(非承诺):快照 running 计数是否恢复 >0。若节点满载但 running 恒 0,
# 属独立显示问题,查 server 日志中 claim 的 "跳过 running 标记" info 行定位。
```
## 回滚预案
若新版出现异常:`docker compose stop server` → 恢复备份(`cp data/dcts.db.bak.<ts> data/dcts.db`,队列库同理)→ 部署旧镜像 → up。清理 SQL 的逆操作不需要(僵尸行清除与翻黑修复都是单向正确方向)。