Skip to content

objectql 的 UPDATE dispatch 没有共享判定函数 —— delete 有 resolveEngineDeleteDispatch,update 的同款三分支只是 engine.ts 里的一个内联 throw #5480

Description

@os-zhuang

发现于 #5393(flow update_record / delete_record 补 multi 批量意图键)的实现过程,PR 见该单。属 PD #10 的范围外发现,不在 #5393 内修(#5393 的 scope guard 明写 packages/objectql 零改动)。

事实(origin/main)

delete 的派发决策已经被抽成生产者侧的唯一判定,任何测试替身都能 import 它:

  • packages/objectql/src/engine-delete-dispatch.ts —— resolveEngineDeleteDispatch / assertEngineDeleteDispatch / scalarDeleteId / ENGINE_DELETE_REJECT_MESSAGE / ENGINE_DELETE_DISPATCH_CASES,全部从 @objectstack/objectql 导出;
  • scripts/check-engine-double-contract.mjs 以「fake 的 delete 是否路由该判定」为门禁,当前 23 pinned / 32 DEBT / 1 exempt。

update 的同款三分支没有对应物:

  • packages/objectql/src/engine.ts 的 update 路径里,标量 where.id → 按 id;否则 options.multi → driver.updateMany;否则 throw new Error('Update requires an ID or options.multi=true') —— 这条 throw 是内联字面量,既没有导出的常量,也没有可复用的判定函数。
  • check-engine-double-contract.mjs 的文件头把这一条列为刻意不覆盖:"every other method a fake engine offers (find filter semantics, update's twin dispatch, unknown-option rejection). Same family, but each needs its own producer-side predicate extracted first. delete had one available because sharing: DELETE /sharing/rules/:idOrName answers 500 for both address forms — rules cannot be deleted over REST #4434 already paid for it."

为什么现在值得记

#5393 在 service-automation 里补真实契约测试时,delete 侧可以用 assertEngineDeleteDispatch 把假引擎钉死在生产者契约上(该文件已被门禁认作 pinned);update 侧只能退而断言执行器交给引擎的 options 包,并在文件头写明「不对引擎会不会接受它发表第二份意见」—— 因为唯一的替代做法是在 fake 里手抄一遍 update 的判定,而那正是 #4434 / #4550 记录的、门禁存在的理由(手抄必然漏掉 where: { id: { $in: [...] } } 看着像 id 其实是谓词这一半)。

也就是说:同一个执行器的两个写入动词,一个能被绑定到生产者契约,另一个结构上不能,而 update_record 的破坏性并不比 delete_record 低多少(谓词 update 覆盖整表字段)。

建议动作

  1. 按 engine-delete-dispatch.ts 的形状抽出 engine-update-dispatch.ts:resolveEngineUpdateDispatch / assertEngineUpdateDispatch / ENGINE_UPDATE_REJECT_MESSAGE,让 ObjectQL.update 自身改用它(生产者与判定必须是同一份,否则又是第二份副本);
  2. check-engine-double-contract.mjs 增加 update 切片,基线按实测填(不要 --fix 式生成);
  3. 顺带可关掉 flow 的 delete_record / update_record 无法表达批量意图 —— 节点 schema 无键、执行器不传 options.multi,谓词批量写对所有 flow 平台级不可达,而节点描述符宣称支持 #5393 留下的这条不对称:packages/services/service-automation/src/builtin/crud-bulk-intent.test.ts 的 update 用例可以升级为同样 pinned。

注:@objectstack/objectql 已在 #5393 中加入 @objectstack/service-automation 的 devDependencies(无环:objectql 的传递依赖闭包 12 个包不含 service-automation),所以第 3 步不再需要额外的依赖变更。这一点也已回填到 scripts/engine-double-contract.baseline.json 里那 8 条 service-automation 条目的 why / closes。

关联:#5393(本发现来源)、#5197(检测器盲点:零参 async delete() 连发现都发现不了)、#4550(门禁本体)、#4434(家族起源)、#4987(metadata-protocol 侧的成环阻塞,与本单无关但同族)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions