auto-sync: 2026-05-16 19:02:29
This commit is contained in:
@@ -183,32 +183,33 @@ class DaemonHealth:
|
||||
|
||||
**设计原则**:状态全在 SQLite,Daemon 无状态。重启 = 重新加载所有项目 + 所有任务状态,继续执行。
|
||||
|
||||
**恢复流程**:
|
||||
**恢复流程(保守策略)**:
|
||||
|
||||
```
|
||||
PM2 检测 Daemon 挂了 → 重启 Daemon
|
||||
│
|
||||
├── 读取 _registry.yaml → 恢复项目列表
|
||||
├── 遍历每个 active 项目 → 打开 SQLite 连接
|
||||
│ └── 读取所有任务状态(pending/working/completed/failed/...)
|
||||
├── 为每个 active 项目启动 ProjectSlot 线程
|
||||
│
|
||||
└── ProjectSlot._tick() 扫描 working 任务
|
||||
└── working 任务 → 重新 spawn Agent(可能冗余执行一次)
|
||||
└── Agent 自己判断:上次做了没有?产出在不在?
|
||||
├── 产出已存在 → 跳过,直接报告完成
|
||||
├── 做到一半 → 继续完成
|
||||
└── 没做过 → 正常执行
|
||||
├── 扫描所有 working 任务 → 标记为 failed(原因: "Daemon restart, agent process lost")
|
||||
├── 启动 ProjectSlot 线程
|
||||
└── 后续 pending 任务正常分配
|
||||
```
|
||||
|
||||
**关键假设**:
|
||||
**为什么不重新执行**:
|
||||
1. Daemon 崩溃是不正常事件,Agent 子进程状态不可预测
|
||||
2. output.json 可能写了一半,重新执行比恢复更安全
|
||||
3. 用户手动 retry 比自动重新执行更可控
|
||||
4. task_attempts 表记录完整,不丢信息
|
||||
|
||||
**关键设计**:
|
||||
1. **SQLite 是真相来源**——所有任务状态、产出记录都在 `.db` 文件里,Daemon 内存无状态
|
||||
2. **Agent 能判断重复**——AI native,Agent 看到 task context + 已有 output 文件,能自主判断是否需要重新执行
|
||||
3. **冗余执行无害**——即使一个节点被多执行一次,结果是幂等的(Agent 会检查产出是否已存在)
|
||||
4. **无限续杯**——重启后 working 节点重新执行,属于已有的"无限续杯"机制(项目内运转机制,不在此设计)
|
||||
2. **SQLite WAL 保护数据完整性**——崩溃时未提交的事务自动回滚
|
||||
3. **ActiveAgentCounter / DaemonHealth 重启后归零**——不需要持久化
|
||||
4. **task_attempts 的 attempt_index 递增**——retry 不覆盖历史
|
||||
|
||||
**不需要额外存储**:
|
||||
- 不需要 checkpoint 文件——SQLite 就是 checkpoint
|
||||
- 不需要 recovery log——task_attempts 表已经记录所有尝试
|
||||
- 不需要 recovery log——`task_attempts` 表已记录每次尝试
|
||||
- 不需要状态快照——每次 tick 从 SQLite 实时读取
|
||||
|
||||
|
||||
Reference in New Issue
Block a user