Skip to content

record-change flow trigger 在 predicate 批量写上:previous 不绑定、record 只是裸 payload —— 官方文档与 showcase 正在教的 transition 起始条件在批量写上不成立 #4862

Description

@os-zhuang

来源

#4775(hook condition fail loud)落地过程中,为核实 B1 错误文案能不能把「改用 record-change flow trigger」写成出路而做的实测。核实结论是不能,#4775 因此没有在错误信息里指这条路(维护者定的硬防线:不允许在修 declared ≠ enforced 的 PR 里于错误信息中再造一个同类缺陷)。核实过程本身暴露出这条独立缺陷,按 PD #10 单独记录。

#4800 相邻但不是同一件事:#4800 是「批量写上 hook 要不要按行触发」的设计卡;本条是 record-change flow trigger 这一层,在批量写上交付给 flow 起始条件的上下文本身就是残缺的。

事实(实测,非推断)

对一次 predicate 批量写(multi: true,无 id):

  1. 引擎只在单 id 分支赋值 previous packages/objectql/src/engine.ts:4888if (priorRecord) hookContext.previous = ...,而 priorRecord 仅在 if (hookContext.input.id) 分支内被 fetch;批量分支始终为 null
  2. plugin-audit 的 __previous 兜底也不覆盖批量。 packages/plugins/plugin-audit/src/audit-writers.ts:425:if (!id) return; // bulk update/delete — too costly to snapshot every row here
  3. flow trigger 读的正是这两个。 packages/triggers/trigger-record-change/src/record-change-trigger.ts:291-293:
    const previous = (ctx.previous ...) ?? ((ctx as ...).__previous ?? undefined);
    → 批量写上 previous 恒为 undefined
  4. record 在批量写上也不是行。 引擎批量分支 result = await driver.updateMany(...) 返回的是受影响行数(number)。buildContextafter && typeof after === 'object' 因此为 false,record 退化成 inputDoc —— 即本次写入的裸 payload,而不是任何一行的状态。
  5. hook 只触发一次,所以即使匹配了 N 行,flow 也只被评估一次。

为什么这条要单独立单

这不是一个理论缺口 —— 官方文档与 showcase 正在教的写法,恰好就落在这一格上:

  • content/docs/data-modeling/formulas.mdxskills/objectstack-formula/SKILL.md §5 教的 transition 写法是 previous.x != ... && record.x == ...;
  • examples/app-showcase/src/automation/flows/index.ts 里至少 10 条 flow 的起始条件是 status == "done" && previous.status != "done" 这个形状(第 39/317/424/671/780/896/976/1064/1148/1463 行等)。

对一次批量更新(例如把一批 task 一次性置为 done),这些 flow 的起始条件面对的是「previous 未绑定 + record 只有 payload」:该触发的自动化要么不触发,要么按一条并不存在的『记录』触发一次,而且没有任何东西会说出来。审计/通知类 flow 的缺失是不可见的缺失。

#4775 的对照值得注意:hook condition 在这一格现在会响亮地失败(B1 专门诊断);而 flow trigger 这一格依然是静默的。同一个平台对同一个物理限制给了两种相反的处理。

可选方向(未拍板,留给维护者)

倾向 A,并与 #4800 一起定方向;若 A 成本过高,B 比 C 更符合本仓已经选定的「declared = enforced」路线。

关联

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