Skip to content

[metadata-protocol] SysMetadataRepository.publishDraft() 把 draft 清理的全部失败都当「并发发布者已抽走」,静默留下一条永远 pending 的 draft 行 #4981

Description

@xuyushun441-sys

发现于 #4867(修同文件两个计数器的 catch { return 1 })。仅记录,未在该 PR 中修改 —— 不属于同一个编号家族,按 Prime Directive #10 单开,未指派。

现象

packages/metadata-protocol/src/sys-metadata-repository.ts,publishDraft() 里(origin/main 约 665–676 行,#4867 的 PR #4980 之后行号会下移):

    // Drop the draft row — it has been promoted. Tolerate races where
    // a second publisher already drained it.
    try {
      await this.delete(ref, {
        parentVersion: draft.hash,
        actor: opts.actor,
        source: opts.source ?? 'sys-metadata-repo.publish',
        intent: opts.intent ?? 'override-artifact',
        state: 'draft',
      });
    } catch {
      // best-effort: a concurrent publisher may have already drained
      // the draft; the active row's authoritative content is intact.
    }

注释只点名了一个原因(并发发布者已经抽走了 draft —— 这时 deleteConflictError,确实良性),catch 却吞掉全部失败:连接抖动、超时、权限不足、驱动错误,以及 draft 在此期间被改写导致的 parentVersion 不匹配。这与 #4728 / #4825 / #4867 是同一族形状 —— 一个良性原因赦免了所有原因,只是这里的数字换成了一行残留数据。

后果

publishDraft() 返回成功,active 行也确实是对的(这一点注释说得没错),但 sys_metadata 里那条 state='draft' 的行还在:

  • Studio / Setup 会继续把这个 artifact 显示为「有未发布的改动」,而它其实已经发布了 —— 用户看到一个点了没用的按钮;
  • 下一次 publishDraft() 会拿这条陈旧 draft 当新内容再发布一次,写出一条内容与 active 完全相同的历史事件(甚至可能把已经被覆盖的旧 body 重新推成 active);
  • 没有任何日志,重试不修、重启也不修。

按 AGENTS.md「Degradation log levels」的那一问:降级之后系统对外看起来完全正常,而它声称已经清理的东西并没有清理 —— 属于 error 那一类,不是 warn

建议(与 #4728/#4825/#4867 一致的形状)

按错误类型判别,只赦免真正良性的那一个:

参考

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions