Skip to content

finding(objectql): archive 的冷侧 keep prune 在 abort 位已抬起后仍发一次 DELETE —— 循环之后的那条腿没跟上 #4747 #5966

Description

@baozhoutao

观察类 finding,来自 #5755 / PR #5956 的实现。今天没有用户会撞到,记录在案由 PM 定级。

事实(origin/main + PR #5956)

PR #5956archiveObject() 的批循环补上了 #4747 的 abort 检查(与 batchedReap 同款)。补完之后,archiveObject()循环之后还剩一条腿没有该检查 —— 冷侧 keep 保留期的 prune:

// (批循环在此 break —— 此时 this.abort.aborted 已确定为 true)

// Cold-side retention: `keep` bounds the archive itself.
if (archive.keep && typeof cold.deleteMany === 'function') {
  const keepCutoff = new Date(this.now() - parseLifecycleDuration(archive.keep)).toISOString();
  await cold.deleteMany(object, { where: { created_at: { $lt: keepCutoff } } });
}

于是 teardown 落在批循环中途时:循环按新检查停下,紧接着仍会向正在关闭的 cold datasource 发一次谓词 DELETE。

为什么值得单独记一条(而不是「单次 await,可接受」)

这与 #5194 之前「无 guard reap 是两个检查点之间的单个 await」的形态不同,差别在于代码是否已经知道答案:

为什么现在不会有人撞到

三重叠加,比 #5755 还窄:

  • archive 策略要求已配置 cold datasource(archive.to),未配置直接 skipped: 'archive-pending';
  • 还要求显式声明 archive.keep(未声明则整条腿不执行);
  • 目前仓内没有平台对象声明 archive,更没有声明 keep

修法(一行,若 PM 认为该修)

把该腿并入同一个判定即可,例如 if (!this.abort.aborted && archive.keep && typeof cold.deleteMany === 'function'),或在其前加一行早退。语义上不存在取舍:cold prune 是纯保留期回收,推迟到下一轮 sweep 无任何副作用(它不像热删那样受「归档成功才热删」的配对约束)。

PR #5956 未顺手改:该 PR 的裁定范围是批循环那一行,且其测试 fixture 有意不声明 keep,以免断言一条本 PR 不治理的腿。

Found-during: #5755 / PR #5956

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions