#4626 (subscribeData/DataEvent 生产者履约)的范围外发现,按第十条军规立案,unassigned。
现象
DataEvent(@objectstack/spec/api)是逐记录 契约:recordId 必填。但 ObjectQL 引擎的批量写路径拿不到记录标识:
IDataDriver.updateMany / deleteMany 的契约返回值是 Promise<number>(受影响行数,见 packages/spec/src/contracts/data-driver.ts),没有行、也没有 id;
引擎 update() / delete() 的 options.multi = true 分支就走这两个方法。
#4626 之前,这两条路径各发一条 伪造事件:payload: { recordId: '', changes, after: <受影响条数> }。它同时骗了两个仓内消费者——webhook auto-enqueuer 收到 recordId: '' 的一次投递,知识同步则把 {recordId, after} 这个信封当成记录写进索引。#4626 按契约优先(不在消费端容错、也不在生产端伪造)改成:批量写不发事件,并 warn 出声 。
于是留下这个真实的能力缺口:
multi: true 的更新/删除不再触发 webhook (此前触发一次,但内容不可用);
知识库 object source 对批量写不同步;
subscribeData 订阅者看不到批量写。
处置方向(需裁决)
逐记录扇出 :批量写前/后按 AST 取一次匹配行(或让驱动 updateMany/deleteMany 返回受影响 id),对每行发一条合规 DataEvent。语义最正,但热路径多一次查询(或改驱动契约,涉及全部驱动)。
新增批量事件类型 :在 DataEventType 里声明 data.records.updated / data.records.deleted(带 object + matched 计数 + 可选的 where),让批量写有自己的诚实 契约,而不是冒充逐记录事件。消费者(auto-enqueuer / 知识同步 / client SDK)按新类型分别处理。
维持现状 :批量写没有实时事件,文档写清楚(client realtime declared ≠ enforced:subscribeData 回调把 RealtimeEventPayload 硬铸成 DataEvent,顶层 recordId/changes/id 运行时是 undefined #4626 已在 content/docs/automation/webhooks.mdx 写明)。
三条都要顺带回答:批量事件是否应进入 webhook 触发器词汇表(create/update/delete 目前是逐记录语义)。
参考
#4626(subscribeData/DataEvent 生产者履约)的范围外发现,按第十条军规立案,unassigned。
现象
DataEvent(@objectstack/spec/api)是逐记录契约:recordId必填。但 ObjectQL 引擎的批量写路径拿不到记录标识:IDataDriver.updateMany/deleteMany的契约返回值是Promise<number>(受影响行数,见packages/spec/src/contracts/data-driver.ts),没有行、也没有 id;update()/delete()的options.multi = true分支就走这两个方法。#4626 之前,这两条路径各发一条伪造事件:
payload: { recordId: '', changes, after: <受影响条数> }。它同时骗了两个仓内消费者——webhook auto-enqueuer 收到recordId: ''的一次投递,知识同步则把{recordId, after}这个信封当成记录写进索引。#4626 按契约优先(不在消费端容错、也不在生产端伪造)改成:批量写不发事件,并 warn 出声。于是留下这个真实的能力缺口:
multi: true的更新/删除不再触发 webhook(此前触发一次,但内容不可用);subscribeData订阅者看不到批量写。处置方向(需裁决)
updateMany/deleteMany返回受影响 id),对每行发一条合规DataEvent。语义最正,但热路径多一次查询(或改驱动契约,涉及全部驱动)。DataEventType里声明data.records.updated/data.records.deleted(带object+matched计数 + 可选的 where),让批量写有自己的诚实契约,而不是冒充逐记录事件。消费者(auto-enqueuer / 知识同步 / client SDK)按新类型分别处理。content/docs/automation/webhooks.mdx写明)。三条都要顺带回答:批量事件是否应进入 webhook 触发器词汇表(
create/update/delete目前是逐记录语义)。参考
packages/objectql/src/engine.ts—publishDataEvent()的 "no record identity → no event" 闸门packages/spec/src/api/events.zod.ts—DataEventType/DataEventSchema