fix(objectql): Archiver 的批循环尊重 #4747 的 teardown abort 位 - #5956
Merged
Conversation
`LifecycleService.stop()` raises an abort bit checked at every leg boundary -- between objects in `sweep()`, and between reap pages since #5753. The Archiver's own batch loop had no such check, so teardown landing mid-archive ran the remaining batches out: up to 20 x 500 rows of `hot.find` + per-row `cold.upsert` + `hot.bulkDelete`, i.e. ~10k operations issued across two datasources the host is already closing. That is the #4747 defect itself, on the one loop #5753 did not reach. Same one-line check as `batchedReap`, at the top of the batch body. Breaking BETWEEN batches preserves the Archiver's safety rule ("hot-delete only what the cold store took"): the batch in flight completes its upsert -> bulkDelete pair, and batches not yet begun are left for the next sweep to re-read. Not reachable today (no platform object declares `archive`), so this is prevention for the first deployment that does. Fixes #5755 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Q7oc7ASjh8yxyS3Yz78We
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
baozhoutao
marked this pull request as ready for review
August 6, 2026 13:22
This was referenced Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5755
前提复核(先于实现)
按 issue 的 lead 逐条对
origin/main(a6b3ee7a1)实读,前提成立(行号已漂,按内容定位):f205c32)a6b3ee7a1)sweep()对象之间:571if (this.stopped) return report;、:598同款batchedReap每页之间:1202if (this.abort.aborted) break;archiveObject批之间:1047的for批循环(上界ARCHIVE_MAX_BATCHES_PER_SWEEP)循环体直接以await hot.find(...)开头一轮 archive 的量级也与正文一致:20 批 × 500 行,每批 = 1 次
hot.find+ 每行 1 次cold.upsert+ 1 次hot.bulkDelete,即最多约一万次跨两个 datasource 的读写。stop() 落在其中任何一点,循环都会把剩余批次跑完 —— 这正是 #4747 停掉的形状,reap 那侧已由 #5753 补上,archive 这侧没有。改动
archiveObject()批循环体开头一行,与:1202同款:外加一段注释,写清两件事:为什么
sweep()的对象间检查不够(一轮 archive 是 20 页跨两个 datasource 的读写),以及为什么按批 break 不破坏 archive 的安全规则「归档成功才热删」—— 在飞的那一批会把upsert→bulkDelete这一对做完,未开始的批次原样留在热库,交给下一轮 sweep 重新读。没有重构循环本身。⛔ 同文件的 #5756(reap 每轮预算按「(对象, where 作用域)」计)是语义取舍、分诊持有中,本 PR 未触碰。
测试(
packages/objectql/src/lifecycle/lifecycle-service.test.ts)驱动真
LifecycleService+ 计数 stub 冷热双 driver(每一条腿都记账:页读、逐行拷贝、热删),加在teardown (#4747)describe 里,与stop() mid-reap那条并列:an archive nobody calls off runs its whole 20-batch budget:不抬 abort 位时页读 20 次、拷贝 10 000 行、热删 20 批,余下 500 行留给下一轮。stop() mid-archive ends the batch loop instead of running out the page budget:在第 2 批的第一行cold.upsert处抬起 abort 位,断言hot.find都没发);[500, 500];hotDeleted.flat()逐项等于copied—— 冷库收下的每个 id 都被热删,且没有任何未被冷库收下的 id 被热删,两个方向都没有半批;archive.keep有意未在该 fixture 上声明:冷侧 prune 是循环之后的单次调用,本 PR 不改那条腿,fixture 也就不去断言它。反向验证(方向先预测,后运行)
预测:标准红 —— 去掉新检查后主用例转红,对照用例保持绿(它从不抬 abort 位,本就无法区分两个版本,这正是它作为对照而非第二个 pin 的原因)。
实跑与预测一致:
恢复该行后 72/72 全绿。
验证
上述数字取自
git merge origin/main(⛔ 未 rebase)之后的重跑 —— 合入的metadata-protocol/protocol.ts与objectql/protocol-meta.test.ts与本改动包重叠,故按 AGENTS §9/§10 重建依赖后整包重跑。新测试未引入新的 fake engine:复用文件内既有的
captureEngine;新增的冷热 stub 是 driver 替身(find/upsert/bulkDelete/deleteMany),不含引擎delete/update派发面,check:engine-double-contract复跑仍为 OK。影响面
今天不可达:archive 策略要求已配置 cold datasource,仓内无平台对象声明
archive,未配置时直接skipped: 'archive-pending'。这是为首个声明archive的部署做的预防,changeset 按@objectstack/objectqlpatch 记。🤖 Generated with Claude Code
https://claude.ai/code/session_019Q7oc7ASjh8yxyS3Yz78We