RFCs

RFC 1859: Artifact Merge

Summary

将 Atomic Memory 的合并与撤销提取为统一方法,并用一套公共数据库表保存合并状态、输入与结果关系及撤销记录。 所有 Artifact Family 都可以接入并直接复用这套方法和表,不需要为各类制品分别建立合并、关系或撤销表。 所有制品的新增和修订统一经过公共写入层(ArtifactRepository 及其共享持久化实现), 正文及版本继续使用已有 Artifact 存储;是否发起合并由各制品业务决定。

Motivation

RFC #1809 定义了“新建合并结果、冻结输入、保留历史、 支持撤销”的方式。PR #1857 的实现分支将相关状态保存在 Atomic Memory 专用表中,并结合结果首版正文中的合并信息和 lineage 确定输入版本。

其他制品需要合并时,也需要记录用了哪些输入、生成了哪个结果、输入何时被冻结,以及撤销时恢复哪些对象。 这些信息可以用通用制品身份和版本表达,无需每个 Family 单独建表、重复实现关系维护和撤销流程。

本提案将这些能力下沉到公共层,Atomic Memory 也通过同一套方法和公共表完成合并与撤销。

Guide-level explanation

合并

调用方提供同一 Scope、同一 Family 内至少两个不同制品的精确版本,以及合并后的内容。 公共方法创建新制品 C,记录 A、B 到 C 的合并关系,并冻结 A、B。 A、B 退出正常使用,正文和历史仍可按精确版本读取;后续修订继续作用于 C。

合并后的内容如何产生由调用方决定。无论来自用户操作还是自动任务,最终都调用同一个公共方法,写入同一套公共表。

撤销

撤销产生 C 的合并时,公共方法从合并记录中找到输入,将 A、B 恢复到合并前状态。 每个实际恢复的输入都在原制品身份下追加新版本,正文来自冻结版本。 只有显式 restore 可以为其目标选择历史正文;undo_merge 不接受历史版本选择。 C 也在原身份下追加新版本记录退役。新版本号均为该制品当前版本加一,旧版本和原始合并关系保留。 C 的后续修订不会自动拆分回 A、B,C 的历史仍可读取,退役身份不重新启用。默认有效读取跟随新版本。

连续合并沿当前仍生效的关系处理。例如 A、B 合并为 C,C 与 D 合并为 E: 恢复 B 时,依次撤销 E、C,恢复 A、B、D,退役 C、E;只撤销 E 时,恢复 C、D,A、B 仍被冻结。 普通证据引用不会触发级联撤销,也不会回滚已使用结果的外部操作。

调用方可以先预览影响,再执行撤销;也可以直接请求撤销,由服务端计算并返回实际影响。 按预览执行时,若相关版本、状态或关系发生变化,应拒绝过期预览,不能扩大已确认的范围。

若无需改变状态,且没有指定历史版本,操作仍为 no-op,不追加版本。

Reference-level explanation

一套公共表

公共表面向 Artifact 保存合并信息,通过 Scope、Family、制品身份和精确版本定位对象,不绑定某一种制品的正文格式。 公共存储需要表达:

  • 一次合并的输入、结果及其精确版本。
  • 输入的冻结状态、合并前状态,以及当前所属的合并结果。
  • 合并关系是否仍然生效,及连续合并之间的关联。
  • 撤销记录中实际恢复、退役对象的新版本精确引用,以及恢复所用的冻结版本或指定历史版本。 这些引用可以由既有版本和来源记录保存,不要求另建操作账本。 实际整组结果可按本次操作的主版本精确引用查询,读取时检查受影响制品的权限。

这些信息由公共层统一维护,是合并与撤销的权威记录。制品正文仍保存在原有 Artifact 版本中,公共表不复制正文。 普通 lineage 继续记录证据关系,不能代替合并记录,也不能据此推断某个制品已经被合并。

接入新 Family 不新增该 Family 专属的合并状态表、关系表或撤销表,也不要求修改公共表结构。 各 Family 不再保存另一套独立的权威合并记录;需要用于检索的派生状态应与公共记录保持一致。 具体表数量、字段、索引和物理布局由后续实现设计确定。

统一方法与接入方式

所有制品的新增和修订最终经过公共 Artifact 写入层,统一维护版本并检查公共合并状态。 各制品可以保留自己的业务入口,但不能绕过公共写入层修改制品正文、版本或合并状态。

公共层同时提供合并、合并关系查询、撤销预览和撤销执行,统一维护冻结、恢复、关系遍历及并发检查。 是否合并、何时合并、选择哪些输入以及如何生成结果,由各制品业务决定。需要合并时,调用方显式提交输入引用和结果内容, 公共合并方法复用同一写入基础,并完成相关状态和关系更新。 新增 Family 无需复制合并算法、编写专属合并存储,或在公共入口增加按 Family 名称判断的分支。

公共写入层不会因为一次普通新增或修订而自动检索相似制品、决定合并或创建合并关系。 普通修订统一检查并拒绝修改被冻结的输入;只有显式合并或撤销操作才执行相应的关系和状态变更。 默认读取和检索同样遵守合并状态,冻结输入和退役结果不能作为当前有效制品使用。 有权限的精确历史读取始终返回原版本,不自动跳转到合并结果。 本提案只提供公共合并能力,不要求同时启用自动检索、内容生成或自动合并。

一致性

合并和撤销检查全部受影响制品的权限、版本、状态及合并关系;生成内容期间的读取不能替代提交时检查。 结果发布、输入冻结、公共关系和相关当前状态一起生效,撤销也整组生效。失败不能留下部分冻结或部分恢复。 恢复、退役所追加的版本和对应当前状态在同一事务中生效。 一个输入只能属于一个仍生效的合并结果,并发操作不能将同一输入合并到两个同时有效的结果。

接入与验收

Atomic Memory 的合并能力从首次落地起直接使用公共方法和公共表,实现 RFC #1809 中的合并与撤销行为。 公共记录是合并与撤销的权威来源,撤销不回退 Source 消费进度。

验收应覆盖 Atomic Memory 和另一个 Family,确认两者使用相同公共方法和公共表,接入时无需新增专属合并表。 同时验证普通写入不会触发合并、各业务入口不能绕过冻结检查,以及连续合并、级联撤销、预览失效、并发竞争、 整组失败和精确历史读取。恢复、退役应在各自原身份下追加下一版本,保留撤销的精确引用; 无变化且未指定历史版本的请求仍为 no-op。

Drawbacks

将 Atomic Memory 的实现提取为公共方法,需要拆分其中与具体制品绑定的部分,并验证多个调用方可以复用同一套行为。 公共方法和表结构成为共同依赖后,后续修改需要验证所有已接入的调用方。

Rationale and alternatives

  • 统一方法和公共表。 共同维护合并与撤销,后续制品接入时复用相同存储,不再重复建表。
  • 只统一接口,各 Family 分别建表。 调用形式一致,但关系存储和撤销逻辑仍重复,不满足本提案的复用目标。
  • 只记录 lineage。 可以表达证据来源,但不能区分普通引用与合并,也不足以确定当前有效关系和撤销范围。

Prior art

RFC #1809 和 PR #1857 提供合并与撤销的行为基础;本提案将其公共化。 RFC #1549 提供 Family 能力注册方向,可用于接入统一方法。

Unresolved questions

公共表的具体结构、已有公共存储的复用方式及方法参数,在实现设计中确定。 这些选择应满足“新增 Family 无需另建合并表”的要求。

本提案不包含跨 Scope 或跨 Family 合并、物理删除和外部副作用回滚。

Future possibilities

基于公共合并记录,可以统一展示合并关系图、查询操作历史和预览撤销影响,无需为每种制品分别实现。

On this page