Skip to content

Flow Diagram:明确外部写入一致性保证并消除 compare→rename 覆盖窗口 #239

Closed

Description

@suntianc

Parent

来源

2026-07-28 对 #200 落地代码的 Spec review。

问题

replaceFileAtomicallyIfUnchanged() 当前执行:

  1. 读取目标文件;
  2. 与 expectedBytes 比较;
  3. await fs.promises.rename(temp, target) 发布新内容。

Project mutation 队列只能串行化 CDF 进程内的写入。任意外部程序仍可在步骤 2 与 3 之间写入目标文件,该写入随后会被 CDF 的 rename 静默覆盖。因此当前实现提供的是“原子发布 + 进程内串行化”,不是 #200 所写的、面向任意外部写入者的原子 compare-and-swap。

现有测试仅覆盖:调用前文件已变化,以及两次 store.saveDocument() 的进程内并发;没有覆盖“比较完成后、发布前”发生外部写入。

必须先完成的决策

标准 Node 文件 API 没有跨平台的“比较现有内容并条件替换”原语,且不合作的外部写入者不会遵守 CDF 的进程锁。因此实现前必须明确产品保证,二选一并记录理由:

A. 严格外部写保护

保证任意外部程序在任何时刻写入都不会被 CDF 静默覆盖。采用此选项时,必须给出可在 macOS / Windows / Linux 上成立的发布协议或明确受支持的平台边界,并用可控竞态测试证明,而不是再次缩短 check→rename 窗口。

B. CDF 内部强保证 + 外部写 best-effort

严格保证所有 CDF 写入者之间不丢数据;对不合作的外部程序只做发布前检测和冲突提示,不宣称无窗口。采用此选项时,必须同步修订 #200 中“原子 CAS / 外部程序不丢修改”的表述、测试口径和用户可见冲突语义,避免实现与承诺继续不一致。

若该保证会成为长期架构约束,按 docs/agents/domain.md 判断是否需要 ADR;不要在代码注释里单独做产品决策。

交付内容

  • 写明选定的保证等级、适用写入者和平台边界。
  • 使 API/type/注释准确表达该保证;禁止继续把 read + rename 称为无条件原子 CAS。
  • 按选定保证实现冲突检测与错误结果。
  • 保留原子发布:读者只能看到旧文件或新文件,不能看到半写文件。
  • 失败和冲突必须保留用户未保存内容,并返回当前磁盘内容/版本。

测试

必须新增一个可控竞态 seam,在“完成 expected 版本校验”与“发布”之间插入外部写入,并断言选定保证下的预期结果。

同时保留:

  • 两个 CDF writer 的交错写入;
  • 创建目标时的并发 EEXIST;
  • 写入失败无临时文件残留;
  • 冲突返回当前内容;
  • 发布中断不产生半写文档。

验收标准

非目标

Activity

  1. added
    bugSomething isn't working
    architecture架构 deepening 候选(来自架构评审)
    needs-infoWaiting on reporter for more information
    P1高优先级 bug
    on Jul 28, 2026
  2. suntianc commented on Jul 29, 2026

    @suntianc
    OwnerAuthor

    已在 #245 完成实现并推送;Ubuntu、macOS、Windows CI 均通过。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1高优先级 bugarchitecture架构 deepening 候选(来自架构评审)bugSomething isn't workingneeds-infoWaiting on reporter for more information

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions