数据韧性架构
wesgine 三层 SQLite 数据模型与 10 条韧性不变量。
三层 DB 架构
每个 Cell 使用三个独立 SQLite 数据库:
| 层 | 文件 | 内容 | 损坏影响 |
|---|---|---|---|
| meta.db | Cell 元数据 | 配置、Agent、Skill 状态 | 不影响 sessions/state |
| sessions.db | 会话数据 | Memory、Sessions | 不影响 meta/state |
| state.db | 运行时状态 | Traces、Observe、Cron | 不影响 meta/sessions |
INV-RESIL-03:单 Layer 损坏不扩散。
Cell 数据目录
{DataDir}/cells/{ID}/
├── meta.db
├── sessions.db
├── state.db
├── skills/
├── knowledge/
├── workspace/{actor}/
├── .scratch/{runID}/
└── .cell.lock
10 条韧性不变量
INV-RESIL-01:Boot 永远成功
无论何种数据损坏,Boot 都返回 nil error。降级是合法状态。
唯一的 boot 失败:ErrCellLocked(进程竞争,非数据问题)。
INV-RESIL-02:Run 永远可用
Runtime().Run() 永远可用。降级只影响历史数据访问。
INV-RESIL-03:单层不扩散
sessions.db 损坏不影响 memory/observe;state.db 损坏不影响 sessions。
INV-RESIL-04:进程排他锁
同一 Cell 同一时刻只有一个写入者:
flock .cell.lock
INV-RESIL-05:快照验证
每次快照后立即 PRAGMA quick_check,损坏快照丢弃。
INV-RESIL-06:Journal 只追加
Journal 文件没有 seek/truncate,只有 O_APPEND 写入。
INV-RESIL-07:损坏文件保留
损坏 DB 归档到 corrupt/ 目录供诊断,不直接删除。
INV-RESIL-08:mmap 禁用
PRAGMA mmap_size=0
消除整类 SQLITE_IOERR_MMAP 故障。
INV-RESIL-09:VACUUM 禁止自动
VACUUM 中断 = 全损。只在 SQLiteBackup(VACUUM INTO)中使用。
INV-RESIL-10:迁移全幂等
任何迁移重跑 N 次结果一致(含多语句 ADD COLUMN)。
快照与备份
SQLiteBackup
resilience.SQLiteBackup(srcPath, dstPath)
使用 VACUUM INTO 原子快照,快照后立即 quick_check。
禁止的备份方式
# ❌ 忽略 -wal / -shm,或只拷一个文件
cp cell.db cell.db.bak
# ✓ 使用 SQLiteBackup
Cell 有 meta.db / state.db / sessions.db 三个数据库,必须全部备份。
降级启动
当某一层数据库损坏时:
Boot
↓ meta.db 损坏?
↓ 标记 Degraded,继续启动
↓ sessions.db 损坏?
↓ 标记 Degraded,继续启动
↓ 所有层就绪
↓ Boot 返回 nil
降级 Cell:
- 新 Run 正常处理 ✓
- 历史数据访问可能失败 ✓
- Observe/Traces 可能不可用 ✓
DSN 配置
所有 SQLite 连接必须包含:
?_pragma=mmap_size(0)&_pragma=journal_mode(WAL)
相关文档
- Cell 生命周期 →
cell-lifecycle.md - CellSpec 总览 →
cellspec-overview.md - 密钥管理 →
secret-management.md