Commit Graph
6 Commits
Author SHA1 Message Date
nyaKazuhaandClaude Fable 5 48ffc08cdf fix(cas): exists 返回 Result 以区分不存在与存储故障
CasRepository::exists(core trait)与底层 Storage::exists 原返回裸 bool,
FileSystemStorage 用 try_exists(...).unwrap_or(false)、infra 适配层吞掉解析/
初始化错误返回 false,调用方无法区分“对象不存在”和权限/IO/初始化故障。

将整条链改为 Result<bool>:
- storage trait 与 FileSystemStorage:try_exists 的 IO 错误经 ? 传播;
- repository FileSystemCasRepository::exists 及 store/add_reference 内部调用;
- core CasRepository::exists trait;
- infra 适配层:解析失败→InvalidArgument、初始化/引擎错误经 map_error 传播。
Ok(false) 仅表示确实不存在。

新增单测:合法但不存在的对象返回 Ok(false),非法 ObjectId 返回 Err(而非静默
false);同步更新各层 exists 断言。

对应 issue #18 维护清单 2-1。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 08:53:54 -07:00
nyaKazuhaandClaude Fable 5 1c4debbaa7 fix(cas): 消除 store/gc 之间的引用计数竞态
store() 原来先 ensure_object(建行 ref_count=0)再 add_reference,两条语句
非事务;即使连接池 max_connections=1,两语句间的 await 也会释放连接,让并发
gc() 在 ref_count=0 窗口删掉刚存的对象文件与元数据(静默丢数据),或使 store
返回 ObjectNotFound。

- 新增 store_reference:单条 UPSERT 原子建行为 ref_count=1 或 +1,对象行不再
  出现 ref_count=0 的可见窗口;store() 与 repository add_reference() 均改用它。
- 新增 delete_zero_ref_metadata:gc 先原子执行 DELETE ... WHERE ref_count=0,
  仅当 rows_affected>0 才删对象文件;被并发递增抢先时跳过,绝不删除仍被引用对象。
  元数据先删、文件后删,最坏只留无元数据的孤儿文件(可覆盖,无数据丢失)。

新增单测:store 后不暴露 ref_count=0(gc_candidates 为空)、候选被重新引用后
gc 跳过、store_reference 原子建行/递增、delete_zero_ref_metadata 守卫。

对应 issue #18 维护清单 1-5。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:39:07 -07:00
nyaKazuha 3c00659691 refactor: reduce quality findings 2026-06-28 15:42:12 +08:00
nyaKazuha 02716d3ccd refactor: address quality findings 2026-06-28 13:04:53 +08:00
nyaKazuha b202d7b231 feat: implement production cas v1 2026-06-28 12:39:17 +08:00
nyaKazuha dd53e3054e chore: establish development baseline 2026-06-28 01:27:09 +08:00