OpenProgram / SessionStore / implementation handoff
Session 注册表时间语义与并发一致性
基线:e831d0f0。本页只规范 meta.json、内存 _index 与 index.json 的时间和并发合同;实现状态与证据见第 07 节。
确定方案。
updated_at 表示最后一次会话内容追加时间,不表示任意元数据持久化时间。内存注册表的读、改、快照由独立锁保护;磁盘原子写串行化,但不在注册表锁内执行文件 I/O。延迟 flush 只能清除自己快照之前的 dirty 状态,不能覆盖并发更新。01 · 已验证缺口与不变量
| 位置 | 当前行为 | 目标不变量 |
|---|---|---|
_persist_meta | 每次写 meta.json 都赋值 time.time()。 | 改名、置顶、已读、分支标记、HEAD 持久化不得改变会话内容排序时间;append 路径显式推进。 |
_index | 更新和 list_sessions() 复制未使用同一把锁。 | 读者获得行字典的点时快照;并发创建、更新、删除不产生迭代异常或撕裂字段。 |
| deferred flush | timer 受锁保护,但快照序列化和其他直接保存路径未形成统一协议。 | 旧快照不得晚于新快照落盘;写入期间的新 mutation 必须保留 dirty 并由后续 flush 保存。 |
02 · 参考机制与取舍
现有 SessionMemoryIndex
节点和 session meta 已有自己的内部锁。采用其“锁内更新、锁外文件 I/O”边界,不增加事务框架。
stdlib threading
采用一把 registry state lock 加一把 write lock。前者保护 dict、dirty、timer;后者只保证磁盘快照按取得顺序写入。
atomic_write_text
继续负责单次文件替换的原子性;不新增数据库、文件锁或第三方依赖。
采用:显式内容时钟、行级浅拷贝快照、串行原子写。修改:_persist_meta 不再隐式更新时间。拒绝:对所有 SessionStore 操作加全局锁、每次 append 同步写 registry、把 updated_at 拆成新字段并迁移全部消费者。
03 · 目标状态流
1
append message/node 显式生成一个时间值,并写入 session meta 与 registry entry。
2rename/pin/read/branch/head 等路径只持久化已有
3updated_at,不自行推进。registry mutation 在 state lock 内完成;
4list_sessions 在同一锁内复制每行后再过滤和排序。保存者先取得 write lock,再在 state lock 内捕获 JSON 快照并清除该快照覆盖的 dirty,随后释放 state lock 执行原子写。
5若写入期间发生新 mutation,它重新设置 dirty;timer 或退出 flush 保存后续快照。
04 · 失败、并发与兼容
- 磁盘写失败保留现有 warning;内存状态仍可服务当前进程,后续 mutation/flush 可再次保存。
list_sessions返回副本,调用方修改返回行不得反向修改 registry。- 创建时调用方提供的历史
updated_at保持原值;重建旧 index 不迁移 schema。 - 排序仍按
updated_at降序,缺失值仍按 0 处理;wire shape 和字段集合不变。 - 不在 registry state lock 内执行
atomic_write_text,避免列表读取被磁盘延迟阻塞。
05 · 明确排除
- 本任务不修改节点 DAG 的并发模型、
mark_merged的跨调用事务或 project location registry。 - 不处理 Windows、系统 credential store、孤儿文件、认证改动和其他审计项。
- 不引入 SQLite、跨进程 registry 锁或新的后台服务。
06 · 验收矩阵
| 公共入口 | 场景 | 可观察断言 |
|---|---|---|
update_session | 创建两会话后改名、置顶、标已读 | 目标会话的 meta/index updated_at 不变,列表顺序不变。 |
append_message | 追加一条内容 | meta/index 同时推进,列表按新时间排序。 |
list_sessions | 调用方修改返回行 | 后续列表结果不受影响。 |
| deferred flush | 旧快照写入期间并发更新 | 后续 flush 后 index.json 包含新字段,不被旧保存清除 dirty。 |
| concurrent registry access | 并发 update/list/flush | 无迭代异常,JSON 始终可解析,最终内存与磁盘一致。 |
07 · 实现文件与证据
| 文件 | 职责 |
|---|---|
openprogram/store/session/session_store.py | 时间语义、registry state/write 锁、快照与延迟 flush。 |
openprogram/store/session/session_node_writer.py | node append 的单一 activity timestamp 与 meta/index 同步。 |
tests/unit/test_session_index_consistency.py | 排序时间、返回快照和并发写入的公共回归。 |
已实现并完成独立审查。 实现提交:9fef648c、09480e0f、c50b5180。规格审查与质量审查均通过;最终 gate 证据记录在任务台账。