Skip to content

finding(objectql): Archiver 的 20 批循环不看 #4747 的 abort 位 —— teardown 期间仍会继续读写正在关闭的 datasource #5755

Description

@os-zhuang

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

事实(origin/main + PR #5753)

LifecycleService#4747 契约是「stop() 抬起 abort 位,sweep 在每个 leg boundary 检查」。目前检查点有两处:

archiveObject() 的批量循环(:1047,for (let batch = 0; batch < ARCHIVE_MAX_BATCHES_PER_SWEEP; batch++))没有这个检查。一轮 archive 最多 20 批 × 500 行,每批是 hot.find + 每行一次 cold.upsert + 一次 hot.bulkDelete —— 即最多一万次跨两个 datasource 的写。stop() 在其中任何一点落下,循环都会把剩余批次跑完。

这正是 #4747 描述的形状:「a sweep already in flight would keep reading and deleting through an engine whose datasource the host is closing underneath it — the reads fail as Unable to acquire a connection」。reap 那一侧已经补上,archive 这一侧没有。

为什么现在不会有人撞到

  • archive 策略要求已配置 cold datasource(archive.to),未配置时 archiveObject 直接 skipped: 'archive-pending' 返回,一行都不搬;
  • 目前仓库里没有平台对象声明 archive(声明 lifecycle 的 11 个对象走的是 retention/ttl);
  • 触发条件还要叠加「teardown 恰好落在一次大批量归档中途」。

所以这是一条为将来第一个真声明 archive 的部署准备的洞,不是当下的故障。

修法

:1202 同款一行:循环体开头 if (this.abort.aborted) break;。注意 archive 的安全规则是「归档成功才热删」,按批 break 不破坏它 —— 每批的 upsert→bulkDelete 已经成对完成,未开始的批次留给下一轮。

Found-during: #5194 / PR #5753

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions