Prototype atomic install recovery (T-103)
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
---
|
||||
id: T-103
|
||||
title: staging/current/backup 原子切换与崩溃恢复原型
|
||||
phase: 1
|
||||
deps: [T-102]
|
||||
status: DONE
|
||||
created: 2026-07-16
|
||||
issue: null
|
||||
context_ref: 0ffeff63e138fcb800f0eee0a8a1d4167f20df09
|
||||
claim_branch: null
|
||||
work_branch: agent/codex/T-103
|
||||
write_paths:
|
||||
- docs/tasks/T-103.md
|
||||
- core/installer/
|
||||
- docs/api.md
|
||||
- docs/04-architecture.md
|
||||
- docs/00-ai-start-here.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
## 问题 / 背景
|
||||
|
||||
安全解压只产生 staging;要让更新可用,还必须在 Windows 文件系统上把 staging 切换为 current,并保证任一步骤崩溃或健康检查失败后都能从磁盘恢复已知安全版本。仅靠内存状态无法覆盖断电/进程退出。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 在 `core/installer` 建立固定目录布局与持久化事务日志 `install-transaction.json`。
|
||||
2. 切换阶段:`prepared → current_backed_up → staging_activated → committed`;健康失败进入 `rollback_required`。
|
||||
3. 每次阶段更新使用同目录临时文件 + journal backup 原子替换;目录切换只使用同一 app 根目录内的 rename。
|
||||
4. 成功健康检查后先写 committed,再清理 backup/journal;失败时把新 current 移出、恢复 backup,失败产物不保留为可启动 current。
|
||||
5. `Recover` 读取主 journal 或中断遗留 journal backup,结合 current/staging/backup 实际存在状态,安全完成回滚/撤销/提交清理。
|
||||
6. 测试通过内部 failpoint 在关键 rename/phase 后模拟进程崩溃,再用新的 Switcher 实例从磁盘恢复。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 有旧 current 的成功更新:新版本成为 current,backup/staging/journal 清理。
|
||||
- 健康检查失败:旧 current 恢复且返回稳定失败;无旧版本时不留下 current。
|
||||
- 在备份后、激活后、committed 后模拟崩溃,新实例 Recover 均得到确定结果。
|
||||
- journal 主文件缺失但 backup 存在时仍可恢复。
|
||||
- 不一致/路径为 symlink/缺 staging/已有未处理 backup 时拒绝,不猜测或删除目录外内容。
|
||||
- Go 1.20 core vet/test 与完整双目标闸门通过。
|
||||
|
||||
## 边界(不改什么)
|
||||
|
||||
- 不实现进程退出检测、真实 EXE 健康协议、installed-app.json(T-202/T-302)。
|
||||
- 不跨卷移动目录;调用者必须把 staging/current/backup 放在同一 app 根目录。
|
||||
- 不清理 `data/`、`licenses/` 或 app 根目录外路径。
|
||||
- 不保留多个历史 backup;多版本备份策略留后续任务。
|
||||
|
||||
## 协作约束
|
||||
|
||||
未启用 Gitea;本任务在 `agent/codex/T-103` 分支串行执行。恢复策略以“未健康检查的新版本不成为可信 current”为最高原则。
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-16:在 `core/installer` 建立固定 app layout、安装事务日志、Switcher 与 Recover;所有 rename/remove 只允许 root 下的 current/staging/backup。
|
||||
- 2026-07-16:事务阶段落地为 `prepared → current_backed_up → staging_activated → committed`,健康失败进入 `rollback_required`;journal 使用临时文件、fsync、主文件/backup 替换。
|
||||
- 2026-07-16:健康成功先写 committed 再清理旧 backup;健康失败把新 current 移出并恢复旧版,首次安装失败则不留下 current。
|
||||
- 2026-07-16:Recover 使用新实例仅凭 journal(或 journal backup)与目录现实恢复;未健康检查的新版本默认回滚/撤销,committed 状态只做清理不降级。
|
||||
- 定向测试通过:成功更新、健康失败回滚、首次安装失败、current rename 后崩溃、staging rename 后崩溃、committed 后崩溃、rollback_required 后崩溃、journal backup、orphan backup、缺 staging、已有 backup、目录/journal symlink。
|
||||
- 2026-07-16:测试模拟的是进程在持久化步骤之间退出;真实断电下目录项落盘顺序与文件锁行为仍需 T-302/T-601 在 Windows VM/真机故障注入验证,不把本原型等同于硬件级断电证明。
|
||||
- 验证通过:Go 1.20.14 core vet/test。
|
||||
- 验证通过:`./scripts/verify_phase0.ps1`,包含 modern/win7 双目标构建、版本/边界与治理检查。
|
||||
Reference in New Issue
Block a user