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 笔误
This commit is contained in:
fmq
2026-08-04 23:40:52 +08:00
parent c8fd24b120
commit cd370d88e7
74 changed files with 13386 additions and 3033 deletions
+121 -37
View File
@@ -46,7 +46,7 @@
### 1.3 限流机制与错误模型 (Rate Limiting & Unified Error)
- **API 限流 (Rate Limiting)**:服务端对敏感接口(如 `/login`、`/node/register`)应用了基于 Governor / 漏桶算法的请求限流器。超出速率上限时返回 `429 Too Many Requests`。
- **API 限流 (Rate Limiting)**:服务端对敏感接口(如 `/login`、`/node/register`)应用了**滑动窗口**sliding window)请求限流器(`rate_limit.rs`。超出速率上限时返回 `429 Too Many Requests`。
- **统一错误格式 (AppError)**:所有 RESTful API 的错误响应均格式化为标准 JSON:
```json
{
@@ -103,23 +103,31 @@
### 2.2 任务规格 (`TaskSpec`)
服务端派发给 Worker 节点的单个计算任务定义。
- **Rust 定义** ([models.rs](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/common/src/models.rs#L98-L106)):
- **Rust 定义** ([models.rs](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/common/src/models.rs#L389-L425)):
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskSpec {
pub task_id: Uuid,
pub point_name: String,
pub params: GridPointParams,
pub task_type: TaskType, // ColdRun | SeedStep
pub seed_point_name: Option<String>,// 步进种子点名称(如适用)
pub task_type: TaskType, // ColdRun | SeedStep(兼容字段 = strategies[0]
pub seed_point_name: Option<String>, // 步进种子点名称(如适用)
pub timeout_sec: u64,
pub workflow_name: Option<String>, // 多工作流分区键
pub wave: i32, // 难度波次
pub tlusty_config: EngineStageConfig, // TLUSTY 阶段配置(enabled/policy/strategies
pub synspec_config: EngineStageConfig, // SYNSPEC 阶段配置
pub synspec_params: Option<serde_json::Value>, // SYNSPEC 数值参数(波长范围等)
pub atmosphere_ref: Option<String>, // 显式大气来源点(仅 SYNSPEC-only 场景)
}
```
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TaskType {
ColdRun,
SeedStep,
`EngineStageConfig`(阶段独立配置,见 `task_engine_decoupling_design.md §3`):
```rust
pub struct EngineStageConfig {
pub enabled: bool,
pub policy: String, // skip_converged | force_recompute | skip_failed
pub strategies: Vec<String>, // 策略链:["cold_run","seed_step"],失败回退弹首项
}
```
@@ -127,6 +135,12 @@
```typescript
export type TaskType = 'cold_run' | 'seed_step';
export interface EngineStageConfig {
enabled: boolean;
policy: string;
strategies: string[];
}
export interface TaskSpec {
task_id: string;
point_name: string;
@@ -134,6 +148,12 @@
task_type: TaskType;
seed_point_name?: string | null;
timeout_sec: number;
workflow_name?: string | null;
wave: number;
tlusty_config: EngineStageConfig;
synspec_config: EngineStageConfig;
synspec_params?: Record<string, unknown> | null;
atmosphere_ref?: string | null;
}
```
@@ -142,7 +162,7 @@
### 2.3 任务上报报告 (`TaskReport`)
Worker 节点向服务端上报的任务计算结果。
- **Rust 定义** ([models.rs](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/common/src/models.rs#L126-L140)):
- **Rust 定义** ([models.rs](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/common/src/models.rs#L496-L513)):
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskReport {
@@ -158,6 +178,7 @@ Worker 节点向服务端上报的任务计算结果。
pub elapsed_sec: f64,
pub error_message: Option<String>,
pub summary_json: String,
pub failed_stage: Option<String>, // "tlusty" | "synspec":失败阶段归因,决定弹哪条策略链
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
@@ -187,6 +208,7 @@ Worker 节点向服务端上报的任务计算结果。
elapsed_sec: number;
error_message?: string | null;
summary_json: string;
failed_stage?: 'tlusty' | 'synspec' | null;
}
```
@@ -237,7 +259,7 @@ Worker 节点向服务端上报的任务计算结果。
node_id: string;
max_slots: number;
active_slots: number;
status: 'online' | 'offline';
status: 'online' | 'offline' | 'pending_approval' | 'disabled' | 'rejected';
cpu_usage: number;
memory_usage: number;
last_heartbeat: string;
@@ -281,9 +303,19 @@ Worker 节点向服务端上报的任务计算结果。
export interface WorkflowSummary {
name: string;
description?: string | null;
status: 'idle' | 'running' | 'paused' | 'completed';
status: 'idle' | 'initializing' | 'running' | 'paused' | 'completed';
created_at: string;
updated_at: string;
stats?: WorkflowListStats | null; // 内联网格点聚合计数(未启动为 null,见 §8.11)
}
export interface WorkflowListStats {
total: number;
converged: number;
failed: number;
running: number;
cold_run_converged: number;
seed_step_converged: number;
}
export interface WorkflowItem {
@@ -328,9 +360,12 @@ Worker 节点向服务端上报的任务计算结果。
{
"status": "pending_approval",
"message": "节点注册申请已成功提交!请在管理 Dashboard 控制台上点击【同意接入】授权该节点",
"node_token": null
"node_token": null,
"registration_secret": "<一次性凭据>"
}
```
> `registration_secret`:节点注册时下发的一次性凭据,节点须在后续
> `/api/node/check_status` 时回传,才能取走待发 token(防止仅知 node_id 的攻击者抢先冒领)。
- `200 OK` (已授权节点带专属 token 刷新配置):
```json
{
@@ -353,15 +388,16 @@ Worker 节点向服务端上报的任务计算结果。
### 3.2 节点心跳保活 (`POST /api/node/heartbeat`)
- **处理函数**: [`heartbeat_node`](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/server/src/api/node.rs#L17-L25)
- **处理函数**: [`heartbeat_node`](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/server/src/api/node.rs#L167-L190)
- **函数签名**:
```rust
pub async fn heartbeat_node(
State(state): State<AppState>,
Extension(auth_node): Extension<AuthenticatedNode>,
Json(req): Json<NodeHeartbeatRequest>,
) -> impl IntoResponse
```
- **鉴权**: 是 (若配置 Token)
- **鉴权**: 是Node 角色必填;`req.node_id` 必须与鉴权身份一致,否则 403
- **请求 Header**: `Content-Type: application/json`
- **请求 Body**:
```json
@@ -376,9 +412,12 @@ Worker 节点向服务端上报的任务计算结果。
- `200 OK` (成功):
```json
{
"status": "ok"
"status": "ok",
"admin_max_slots": 4
}
```
> `admin_max_slots`:管理员强制的并发槽位配额(`null` = 无限制,沿用物理 `max_slots`)。
> 节点据此动态调整本地 `effective_max_slots`(见 `dynamic_cpu_slots_design.md`)。
- `200 OK` (失败):
```json
{
@@ -415,12 +454,14 @@ Worker 节点向服务端上报的任务计算结果。
"node_id": "node-worker-01",
"status": "online",
"token_status": "active",
"token_issued_at": "2026-07-28T12:00:00Z"
"token_issued_at": "2026-07-28T12:00:00Z",
"admin_max_slots": 4
}
]
}
```
> `token_status` 取值:`active`(有效)/ `none`(无凭据记录)。token 失效靠重发覆盖 hash 实现,不存在「已吊销」中间态。
> `admin_max_slots`:管理员强制并发槽位配额(`null` = 无限制),Dashboard 据此渲染节点配额状态。
#### 2. 同意节点接入申请 (`POST /api/admin/nodes/:node_id/approve`)
- **权限**: Admin 角色
@@ -459,6 +500,22 @@ Worker 节点向服务端上报的任务计算结果。
-H "Authorization: Bearer <ADMIN_TOKEN>"
```
#### 7. 调整节点并发配额 (`POST /api/admin/nodes/:node_id/quota`)
- **权限**: Admin 角色
- **说明**: 动态调整节点并发槽位配额上限(不重启 Worker 进程,经下一次心跳响应下发生效)。传 `null` 解除限制,恢复物理 `max_slots`。详见 `dynamic_cpu_slots_design.md`。
- **请求 Body**:
```json
{ "admin_max_slots": 4 }
```
- **响应**:
- `200 OK`: `{"success": true, "message": "节点配额已更新"}`
- **curl 示例**:
```bash
curl -X POST http://localhost:8090/api/admin/nodes/node-worker-01/quota \
-H "Authorization: Bearer <ADMIN_TOKEN>" -H "Content-Type: application/json" \
-d '{"admin_max_slots": 4}'
```
---
## 4. 任务调度与结果上报 API (Task Processing)
@@ -470,9 +527,12 @@ Worker 节点向服务端上报的任务计算结果。
- **处理函数**: [`claim_task`](file:///home/fmq/program/tlusty/tl208-s54/dcts/crates/server/src/api/task.rs#L15-L25)
- **函数签名**:
```rust
pub async fn claim_task(State(state): State<AppState>) -> impl IntoResponse
pub async fn claim_task(
State(state): State<AppState>,
Extension(auth_node): Extension<AuthenticatedNode>,
) -> impl IntoResponse
```
- **鉴权**: 是 (若配置 Token)
- **鉴权**: 是(Node 角色必填;服务端据注入身份校验节点是否被停用)
- **请求 Body**: 无
- **响应 Schema**:
- `200 OK` (有可计算任务):
@@ -533,21 +593,23 @@ Worker 节点向服务端上报的任务计算结果。
```rust
pub async fn report_task(
State(state): State<AppState>,
Extension(auth_node): Extension<AuthenticatedNode>,
mut multipart: Multipart,
) -> impl IntoResponse
```
- **鉴权**: 是 (若配置 Token)
- **鉴权**: 是(Node 角色必填;服务端据注入身份做任务归属校验 `verify_task_claim`,防跨节点伪造)
- **请求格式**: `multipart/form-data`
- Part `report`: JSON 字符串 (映射为 `TaskReport`)
- Part `seed_file` *(可选)*: 二进制数据 (收敛网格点的 `.7` 大气结构种子文件)
- **响应 Schema**:
- `200 OK` (成功):
- `200 OK` (成功 / 幂等重放):
```json
{
"status": "ok",
"message": "上报成功"
}
```
> **幂等重放**:已结算任务(终态守卫已吸收)的重复/迟到上报仍返回 200,并补写种子,不重复结算。
- `400 Bad Request` (缺少 `report` 字段):
```json
{
@@ -562,7 +624,10 @@ Worker 节点向服务端上报的任务计算结果。
"message": "无法解析 params 或 summary_json"
}
```
- **说明**: 当 `converged == true` 且 `atmosphere_has_nan == false` 且包含 `seed_file` 时,服务端会将种子保存至 `seeds_dir/<point_name>/<point_name>.7` 并记入 `seeds` 表。若冷启动任务失败,服务端会自动唤醒 `GridScheduler` 触发针对该网格点的步进回退算法 (Seed-step Fallback)
- `409 Conflict` (任务归属校验失败): 任务被其它节点重新领用、或队列中已无该 task_id(已被结算清理)。此时返回冲突,不写库
- **说明**:
- 当 `converged == true` 且 `atmosphere_has_nan == false` 且包含 `seed_file` 时,服务端会将种子原子写入 `seeds_dir/<point_name>/<point_name>.7` 并记入 `seeds` 表(源精度 `point_name`)。
- 失败上报(未收敛 / 失败 / 超时)且 `state_changed == true` 时,服务端才触发**策略链回退**(`trigger_strategy_fallback`,按 `failed_stage` 弹 TLUSTY 或 SYNSPEC 策略链);被终态守卫吸收的重复失败(`state_changed=false`)不再触发,杜绝重复派发涡旋(2026-08-02 修复)。
- **curl 示例**:
```bash
curl -X POST http://localhost:8090/api/task/report \
@@ -591,6 +656,7 @@ Worker 节点向服务端上报的任务计算结果。
- **请求格式**: `multipart/form-data`
- Part `report`: 旧版 `conv.json` 的**原文 JSON**(映射为 `ModelSummary`,服务端解析出 `name` / `params` / `converged` / `final_max_relc`
- Part `seed_file`: 二进制数据(`.7` 大气种子文件;收敛点必传)
- Part `success_method` *(可选)*: 文本 `cold_run` / `seed_step`。由 `tools/import_results` 依据旧 `conv.json` 的 stages 是否含 `seed_nc` 判定后设置,决定导入点最终归因(缺省按 seed_step 统计)
- **Query 参数**: `workflow`(可选,默认 `imported`):目标工作流名,种子导入到该工作流的 `grid_points`。
- **命名保真**: `point_name` 取旧 `conv.json` 的 `name` 字段(源精度真名,如 `t20000_g5.0_...`),**逐字符**落库(磁盘目录、`grid_points.name`、`seeds.point_name`),与旧版 Python `gen_input5.model_name` 完全一致。
- **幂等**: `ON CONFLICT DO NOTHING` upsert `grid_points`、`conv.json` 与 `.7` 原子覆盖写,可重复运行。
@@ -742,15 +808,19 @@ Worker 节点向服务端上报的任务计算结果。
"grid_stats": {
"total": 512,
"pending": 210,
"queued": 60,
"running": 32,
"converged": 260,
"failed": 10
"failed": 10,
"cold_run_converged": 200,
"seed_step_converged": 60
}
}
```
> `grid_stats` 为**全部工作流的合计**(跨工作流全局聚合)。多工作流并发运行时,此处展示所有
> 工作流 grid_points 的汇总进度;如需查看单个工作流的进度,可读取该工作流各自的 grid_points 统计
> `Database::get_grid_summary_stats(Some(workflow_name))`)。
> 工作流 grid_points 的汇总进度;`queued` 与 `pending` 分开计数(多工作流分区新语义),
> `cold_run_converged` / `seed_step_converged` 为收敛手段归因;如需查看单个工作流的进度,
> 可读取该工作流各自的 grid_points 统计(`Database::get_grid_summary_stats(Some(workflow_name))`)。
- **curl 示例**:
```bash
curl -X GET http://localhost:8090/api/status \
@@ -881,7 +951,6 @@ Worker 节点向服务端上报的任务计算结果。
"success": true,
"message": "成功获取工作流详情",
"data": {
"id": 1,
"name": "sdB_cno",
"description": "sdB CNO 6D Stellar Atmosphere Grid",
"config_yaml": "...",
@@ -944,13 +1013,13 @@ Worker 节点向服务端上报的任务计算结果。
AxumPath(name): AxumPath<String>,
) -> impl IntoResponse
```
- **说明**: 校验工作流,解析 YAML 中定义的所有 6 维网格坐标点,通过 `GridScheduler::initialize_grid` 展开网格点并计算保序难度 Wave,写入 SQLite 任务队列并开启节点调度
- **说明**: 以原子 CAS`transition_workflow_to_initializing`)抢占启动权,随后**异步 spawn** 网格初始化:解析 YAML 的 6 维网格点、按 policy 决定点状态(跳过收敛/打回失败)、展开并计算保序难度 Wave、把 pending 点推入 MQ 开启节点调度。接口先返回 200,后台推进为 `running`
- **响应 Schema**:
- `200 OK` (成功启动):
- `200 OK` (成功启动,后台初始化中):
```json
{
"success": true,
"message": "工作流 'sdB_cno' 已成功启动并安排计算任务",
"message": "工作流 'sdB_cno' 已进入后台异步建立与挂载流程",
"data": null
}
```
@@ -962,6 +1031,14 @@ Worker 节点向服务端上报的任务计算结果。
"data": null
}
```
- `409 Conflict` (并发启动,初始化抢占失败):
```json
{
"success": false,
"message": "工作流 'sdB_cno' 初始化抢占挂起异常,请稍后重试",
"data": null
}
```
- `404 Not Found`:
```json
{
@@ -1028,7 +1105,6 @@ Worker 节点向服务端上报的任务计算结果。
"failed": 3,
"cold_run_converged": 220,
"seed_step_converged": 41,
"imported_converged": 0,
"waves": [
{ "wave": 0, "total": 108, "converged": 108, "failed": 0 }
],
@@ -1037,6 +1113,8 @@ Worker 节点向服务端上报的任务计算结果。
}
}
```
> 收敛手段归因仅 `cold_run_converged` / `seed_step_converged` 两字段;**无独立
> `imported_converged`**——历史导入点统一按 seed_step 途径计入(`success_method` 语义见 §8.8)。
> `avg_point_sec` = `AVG(COALESCE(tasks.elapsed_sec, created_at→completed_at 时间戳差))`——
> 优先用 Worker 回报的精确墙钟(不含排队等待),历史无 `elapsed_sec` 的行回退时间戳差近似;
> `eta_sec` = `avg_point_sec × (total - converged - failed) ÷ 在线节点总槽位`(并发感知;
@@ -1048,14 +1126,14 @@ Worker 节点向服务端上报的任务计算结果。
- **处理函数**: `get_workflow_points``crates/server/src/api/workflow.rs`
- **权限**: Admin
- **用途**: 详情页"网格点明细"表与"收敛性分析"热力图、概览"最近动态"流的数据源。
- **用途**: 详情页"网格点明细"表与"收敛性分析"Parallel Sets 平行集合图)、概览"最近动态"流的数据源。
每行附带**最近一次尝试**信息(`tasks` 关联子查询取最新行,从未派发过的点 `last_*` 为 null)。
- **查询参数**(全部可选,枚举值白名单校验,非法 → `400`:
| 参数 | 取值 | 默认 |
| :--- | :--- | :--- |
| `status` | `pending`/`queued`/`running`/`converged`/`failed` | 不过滤 |
| `method` | `cold_run`/`seed_step`/`imported` | 不过滤 |
| `method` | `cold_run`/`seed_step`(白名单**不含** `imported`,传入即 `400` | 不过滤 |
| `wave` | 整数波次 | 不过滤 |
| `q` | 点名子串(LIKE 通配符已转义) | 不过滤 |
| `sort` | `wave`/`teff`/`max_relc`/`attempts`/`last_completed_at` | `wave` |
@@ -1167,13 +1245,17 @@ Worker 节点向服务端上报的任务计算结果。
"running": 8, "converged": 261, "failed": 3 }
],
"rate_per_hour": 12.5,
"now": "2026-07-31T09:00:00Z",
"done_rate_per_hour": 11.0,
"rate_span_hours": 23.5,
"stalled_minutes": 0.0
}
}
```
> `series` 超 300 条自动降采样(首末点保留);`rate_per_hour` = 窗口首末
> converged 增量 ÷ 时长(快照不足 2 条为 null);`stalled_minutes` = 终态数
> converged+failed)最后一次增长至窗口末端的分钟数(前端 >10 分钟触发停滞预警)。
> converged 增量 ÷ 时长(快照不足 2 条为 null);`now` = 服务端当前 UTC 时刻(前端锚定曲线右缘);
> `done_rate_per_hour` = 终态完成速率(用于 ETA);`rate_span_hours` = 速率统计实际时间跨度;
> `stalled_minutes` = 终态数(converged+failed)最后一次增长至窗口末端的分钟数(前端 >10 分钟触发停滞预警)。
---
@@ -1213,11 +1295,13 @@ Worker 节点向服务端上报的任务计算结果。
| HTTP 状态码 | 触发场景说明 | 响应格式 | 核心原因与解决建议 |
| :--- | :--- | :--- | :--- |
| **`200 OK`** | 请求正常处理 | JSON / Binary Stream | 操作成功执行。 |
| **`400 Bad Request`** | 参数校验失败、缺失关键字段YAML 格式错误 | `application/json` / Plain Text | 检查请求 JSON 结构,验证 YAML 配置语法是否正确。 |
| **`400 Bad Request`** | 参数校验失败、缺失关键字段YAML 格式错误或枚举白名单拒绝 | `application/json` / Plain Text | 检查请求 JSON 结构,验证 YAML 配置语法,确认 `method`/`sort`/`order` 等枚举在合法取值内。 |
| **`401 Unauthorized`** | 鉴权失败或缺失 Authorization Header | `application/json` | 确认环境变量配置,并在 Request Header 中包含正确的 Token。 |
| **`403 Forbidden`** | 身份校验失败(心跳 `node_id` 与鉴权身份不匹配、跨点上报拒绝、角色权限不足) | `application/json` | 确认节点 token 与上报身份一致,检查 RBAC 角色。 |
| **`404 Not Found`** | 资源、种子文件或工作流不存在 | `application/json` | 校验请求 URL 中的资源文件名或工作流 `name` 是否拼写无误。 |
| **`429 Too Many Requests`** | API 请求超出速率限制(限流生效) | `application/json` | 降低请求频率或配置漏桶/令牌桶容量参数。 |
| **`409 Conflict`** | 状态冲突:节点停用/启用状态不支持、start 初始化抢占失败、report 任务归属校验失败 | `application/json` | 检查目标状态是否合法,或稍后重试。 |
| **`429 Too Many Requests`** | API 请求超出速率限制(滑动窗口限流生效) | `application/json` | 降低请求频率;限流为滑动窗口实现(`rate_limit.rs`),非漏桶。 |
| **`500 Internal Server Error`** | 服务端数据库错误、I/O 打开失败或队列异常 | `application/json` | 检查服务端日志以进一步厘清 SQLite 锁冲突、磁盘空间或资源路径问题。 |
---
*文档生成于 2026-07-27 | DCTS Server 0.1.0*
*文档生成于 2026-07-272026-08-04 更新以对齐阶段独立配置 / 多工作流隔离 / 节点配额 / 失败阶段归因。*