Files
DCTS/docs/task_engine_decoupling_design.md
T
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

222 lines
14 KiB
Markdown
Raw 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.
# DCTS 任务计算引擎解耦与阶段独立配置架构设计方案
## 1. 背景与现状分析 (Background & Current Bottlenecks)
### 1.1 现状与概念降维问题
在 DCTS 早期版本中,任务类型通过单级平铺枚举 `TaskType`(如 `ColdRun`, `SeedStep`)定义。它将 TLUSTY 阶段的“初始猜想策略”、SYNSPEC 阶段的执行与否,以及全局任务的生命周期强行绑定在一起,导致概念降维与严重耦合。
### 1.2 组合爆炸风险
随着扩展能力(如 `Interpolation`, `LineListScan`)的加入,平铺枚举会导致 $N \times M$ 的组合爆炸,引发代码中大量的硬编码匹配分支。
### 1.3 `runner.rs` 与 `executor.rs` 的硬编码耦合问题
现存节点端代码将执行顺序与文件依赖硬编码,例如必须检查 `TaskType::SeedStep` 才能下载大气文件,无法灵活应对只运行光谱合成的场景。
---
## 2. 独立阶段配置架构设计 (Stage-Based Independent Configuration)
为了实现极高的灵活性并彻底避免组合爆炸,摒弃全局单一的 `TaskType` 枚举绑定,将 TLUSTY 和 SYNSPEC 视为平级的**独立阶段 (Stage)**。
对每一个计算阶段,均提供正交的三个配置维度:
1. **启用开关 (Enabled)**:布尔值,决定当前任务流是否要执行该阶段。
2. **执行策略 (Execution Policy)**:启动工作流时对历史终态点的处理逻辑(跳过收敛/重试失败、强制重算、跳过收敛及失败)。注意:策略只决定**启动时**对终态点的处理;失败后的策略链回退由策略链(§4.2)独立驱动,不受策略门控(2026-08-04 语义修正)。
3. **计算策略 (Compute Strategy)**:该阶段所采用的具体科学计算方法。
### 2.1 独立阶段正交模型
**阶段一:TLUSTY 大气结构求解**
- **Enabled**: `true` / `false`
- **Policy**: `SkipConverged` (默认:跳过收敛·重试失败) / `ForceRecompute` (全量重算) / `SkipFailed` (跳过收敛及失败)
- **Strategy**: `ColdRun` (冷启动) / `SeedStep` (种子推演)(系统已预留扩展其他策略如网格内插的接口)
**阶段二:SYNSPEC 光谱合成**
- **Enabled**: `true` / `false`
- **Policy**: `SkipConverged` / `ForceRecompute` / `SkipFailed`
- **Strategy**: `Standard` (标准)(系统已预留扩展如多分辨率展宽、线表扫描等策略接口)
### 2.2 典型场景映射
此设计允许前端灵活组装出任意复杂度的科研计算流:
- **场景 A(新网格生成)**TLUSTY [启用, 增量, ["cold_run", "seed_step"]] + SYNSPEC [启用, 增量, ["standard"]]
- **场景 B(仅更新光谱)**TLUSTY [关闭] + SYNSPEC [启用, 强制重算, ["standard"]]
- **场景 C(强制更新大气)**:TLUSTY [启用, 强制重算, ["seed_step"]] + SYNSPEC [关闭]
---
## 3. 数据模型与阶段配置结构设计 (Domain Model)
在底层核心结构 (`TaskSpec`) 中,我们将原有的单级平铺类型彻底废弃,转而采用**嵌套式单阶段配置模型 (`EngineStageConfig`)**(注:为避免与 `common::config::StageConfig` 迭代步进参数同名冲突,阶段配置统命名为 `EngineStageConfig`)。
- **`EngineStageConfig` 结构说明**
每一个阶段(无论是 TLUSTY 还是 SYNSPEC)都会拥有一个独立的 `EngineStageConfig` 对象,包含以下三个核心字段:
1. `enabled`: 布尔值。是否在当前计算流中启用该阶段。
2. `policy`: 枚举。决定**启动工作流时**对历史终态点的处理,可选值为:
- `SkipConverged`: 跳过已收敛、重试已失败(启动时把失败点打回 pending 重试,收敛点保留)。
- `ForceRecompute`: 强制重算(启动时收敛 + 失败全部打回 pending,无视历史状态与产物)。
- `SkipFailed`: 跳过收敛及失败(启动时收敛和失败点都保留,只算从未计算过的点)。
- 失败后的策略链回退不受策略门控,只由 `strategies` 链(回退优先级排序)驱动。
3. `strategies`: 策略链队列。存储该阶段的计算策略组合,例如 `[ColdRun, SeedStep]`
- **`TaskSpec` 根模型重构**
原有的 `task_type` 被标记为向后兼容保留字段,新增了:
- `tlusty_config`: 对应 TLUSTY 阶段的 `EngineStageConfig` 实例。
- `synspec_config`: 对应 SYNSPEC 阶段的 `EngineStageConfig` 实例。
- 保留旧版 `task_type` 作为废弃兼容字段,主要用于 Serde 反序列化历史遗留任务或在途 MQ 消息,并在 `normalize_compat()` 方法中自动映射到新的嵌套结构。
---
## 4. 数据库与流转设计 (Database & Scheduler Lifecycle)
### 4.1 数据库结构升级
任务表 (`tasks`) 需要打平阶段配置,彻底移除阶段绑定关系。
- **新增阶段控制字段**
- 为 TLUSTY 新增 `tlusty_enabled` (布尔)、`tlusty_policy` (文本)、`tlusty_strategies` (JSON 数组,默认 `["cold_run"]`)。
- 为 SYNSPEC 新增 `synspec_enabled` (布尔)、`synspec_policy` (文本)、`synspec_strategies` (JSON 数组,默认 `["standard"]`)。
- 新增 `atmosphere_ref` 用于显式关联大气网格点。
- **移除冗余旧字段**
- 在数据库层面移除旧的 `task_type` 列(或保留为 NULL 兼容列)。注:原数据库并无 `pipeline_scope` 列,无需清理。
### 4.2 Strategy Chain 自动链式回退机制 (Scheduler-Level)
原本硬编码在 `config.yaml` 中的 `seed_step_fallback` 逻辑,在本次重构中**升级为更为通用的“策略链 (Strategy Chain)”机制 (`tlusty_strategies`)**。用户可以选择一个或多个策略并排序,形成执行队列。
它的工作流如下:
1. **节点执行当前策略**:Node 接收到任务后,总是读取并执行队列中的第一个策略(例如 `tlusty_strategies[0]``ColdRun`)。
2. **失败上报**:当该策略执行失败时,Node 向 Server 报告任务失败 (`Failed`)。
3. **调度介入弹出队列**:Server 接收到失败报告后,检查 `tasks` 表中的 `tlusty_strategies` 数组。
- 若数组中只有一个元素,说明策略链耗尽,任务彻底失败。
- 若数组中还有后续元素(如 `[ColdRun, SeedStep]`),Server 会将失败的 `ColdRun` 从队列中弹出。
4. **生成新任务指令**Server 将该网格点重置为 `Pending` 状态,并为其生成**下一顺位策略**的任务指令:
- `tlusty_strategies: ["seed_step"]` (剩下的策略链)
- **不修改**原有的 `tlusty_policy` 字段(保持用户的初始配置,避免状态污染)。策略链回退只由策略链驱动(2026-08-04 语义修正:移除策略门控);若用户不想重试失败点,用单策略链(如 `["cold_run"]`+ `SkipFailed` 表达。
- `seed_point_name: 'xxx'` (如果是 SeedStep,Server 在此时负责在全局网格中寻找已收敛邻居点并注入)
5. **节点无感知执行**:Node 再次拉取到任务时,继续单纯地执行当前队列头部的 `SeedStep` 策略即可。Node 在准备运行新策略前,会自动清理该网格点上一轮策略留下的故障标记;节点对“回退过程”完全无感知,实现了全局调度与局部计算的完美解耦。
注:`synspec_strategies` 的自动弹栈与回退机制与 TLUSTY 保持完全一致(若配置了多策略链)。
---
## 5. 节点 Runner 与沙箱执行逻辑 (Node Executor)
在 DCTS 架构中,Node 采用**单任务独立沙箱 (`data/work/task_<task_id>`)** 执行流,并在完成后清理沙箱 (`cleanup_slot_work_dir`)。Server 端的 Scheduler 在生成 `TaskSpec` 时已依据网格数据库状态计算好当前任务指令,Node 仅需依指令执行:
1. **TLUSTY 阶段沙箱执行**
- 首先判断 `tlusty_config.enabled` 开关。若为 `false` 则跳过 TLUSTY 阶段。
- 若开启,Node 读取 `tlusty_config.strategies` 数组的第一项策略。
- 若策略为 `SeedStep`Node 凭 `seed_point_name` 自动向 Server API 异步下载种子 `.7` 大气文件并放入沙箱工作目录,随后调用 `ExecutionRunner` 启动 TLUSTY 迭代计算。
2. **SYNSPEC 阶段沙箱执行**
- 独立判断 `synspec_config.enabled` 开关。若为 `false` 则跳过。
- 若开启,Node 校验当前沙箱或关联的大气产物是否存在:若 TLUSTY 阶段刚完成则直接复用沙箱内 `.7` 文件;若为单独运行 SYNSPEC 场景(TLUSTY 关闭),Node先查看本地result目录是否有.7文件并复制到沙箱,如果没有再 凭 `atmosphere_ref`(或 `point_name`)自动向 Server/存储拉取目标 `.7` 文件放入沙箱。
- 读取 `synspec_config.strategies` 的第一项策略(如 `Standard`),调用 SYNSPEC 二进制进程合成光谱,并按照白名单将结果归档至result。
这种沙箱无状态机制完美切合节点端的生命周期,既保证了节点的干脆利落,又实现了与服务端全局调度的彻底解耦。
---
## 6. 前端 Dashboard 设计 (UI Design)
针对恒星大气网格工作流的主页 UI 进行大幅精简与重构。
### 6.1 移除冗余组件
- **移除卡片下方操作按钮**:彻底删除每个工作流卡片下方的“YAML配置”、“启动”、“暂停”等老旧按钮,工作流的启动配置将收敛至全新的内嵌配置面板。
- **移除收敛手段归因图表**:删除工作流首页中缺乏实际参考价值的“收敛手段归因”模块,为全新的任务调度引擎配置面板腾出空间。
### 6.2 工作流内嵌启动面板 (Embedded Task Configuration Panel)
不再使用弹窗 (Modal) 形式,而是直接将任务阶段独立配置面板**内嵌**在工作流详情页或首页的卡片内部,给予用户最直观且最大化的自由配置能力。
**2026-08 补充**:面板**默认折叠成一行**(标题 + 状态 + 操作按钮:YAML 配置 / 导出 / 暂停 / 删除 / 保存),点「启动配置 ▾」展开——折叠态下主按钮即「启动配置」(展开核对 TLUSTY/SYNSPEC 设置后再点真正的「启动」;工作流运行中该按钮退化为「配置 ▾」,且「启动」仅在展开态出现、避免误触发)。展开后 TLUSTY/SYNSPEC 两张阶段卡**左右并排**(宽屏两列,窄屏自动退化为单列),高度比纵向叠放减半。折叠状态跨轮询保持,展开中的编辑不因折叠丢失。
UI 布局草图如下:
```
+-------------------------------------------------------------------------+
| Workflow Execution Engine: o_star_grid_v1 |
+-------------------------------------------------------------------------+
| |
| [x] TLUSTY Atmosphere Computing Stage |
| Policy: [ Skip Converged (Incremental) v ] |
| Strategy Chain (Ordered by fallback priority): |
| 1. [ Cold Run v ] (X) |
| 2. [ Seed Step v ] (X) |
| + Add Fallback Strategy |
| |
| --------------------------------------------------------------------- |
| |
| [x] SYNSPEC Spectrum Synthesis Stage |
| Policy: [ Force Recompute v ] |
| Strategy Chain: |
| 1. [ Standard v ] (X) |
| |
| [ Save Config ] [ Start Grid ] |
+-------------------------------------------------------------------------+
```
前端 Payload 发送格式:
```json
{
"tlusty_config": {
"enabled": true,
"policy": "skip_converged",
"strategies": ["cold_run", "seed_step"]
},
"synspec_config": {
"enabled": true,
"policy": "force_recompute",
"strategies": ["standard"]
}
}
```
---
## 7. 兼容与部署限制(2026-08 审查补充)
### 7.1 滚动升级约束:阶段开关需全集群新节点
`task_type` 兼容字段只向后兼容 TLUSTY 策略(`cold_run` / `seed_step`)——旧节点仍能据此
区分冷启动与种子步进。但 **`enabled` 阶段开关无法传达给旧节点**
- TLUSTY-only 工作流(`synspec_stage.enabled: false`)在旧节点上仍会执行光谱合成;
- SYNSPEC-only 工作流(`tlusty.enabled: false`)在旧节点上被当作普通 cold_run+synspec 任务,
语义退化(需自带种子/大气才能成功)。
因此启用**阶段开关**(非默认双开)的工作流,须确保集群内全部节点已升级到支持阶段配置的
版本,否则节点行为与工作流意图不符。纯默认配置(双阶段启用)不受影响。
### 7.2 policy 决策取派发时快照(不随 YAML 漂移)
策略链回退(§4.2)的**策略链**与回退任务继承的 policy 均取**派发时落库的 DB 快照**
`tasks` 表的 `*_policy` / `*_strategies` 列,见 `FallbackSnapshot`),与 §4.2「不修改原有
policy,保持用户初始配置」语义一致。2026-08-04 起策略不再门控回退(回退只由策略链驱动),
但 policy 仍随重试任务落库,供审计与下次启动时的策略重置逻辑消费。数值参数
`synspec: {wstart/wend/...}``timeout_sec`)仍取当前 YAML(用户编辑意图优先),形成
「旧链 / 旧 policy + 新数值参数」的混合口径——这是有意取舍:策略链与 policy 是任务级
回退语义记录必须用派发时的,运行参数允许跟随最新配置。
### 7.3 完整 YAML 编辑器(数值参数编辑通道)已恢复
内嵌面板(§6.2)只编辑阶段三维配置(enabled / policy / strategies);`synspec:` 数值参数块
(波长范围、展宽、截断等)不在面板编辑范围。**2026-08 补充**:引擎面板新增「YAML 配置」按钮,
恢复原 `yamlEditor.js` 的完整 YAML 查看/编辑弹窗(语法高亮 + 行号 + 脏状态守卫 + 运行中锁定 +
服务端校验错误内联横幅),数值参数等完整配置均可在此查看与修改后直接保存(PUT
/api/workflows/:name)。该弹窗与内嵌面板的保存互相独立、以各自编辑内容为准——二者维度正交:
面板管执行语义(阶段开关/策略),弹窗管完整配置(含数值参数)。