Skip to content

Once framework#1867 ships: replace the 5 denormalized rollup workarounds with live cross-object rollups #84

Description

@os-zhuang

背景

有 5 个模板因为 framework#1867(hook 沙箱在嵌套跨对象写入时崩溃 memory access out of bounds)把 header/rollup 字段降级成了「手工维护的存储字段」。各 CHARTER / hooks 里都明确记着这个原因,例如 packages/compliance/src/hooks/index.ts:

compliance_control.last_status / last_assessed_at are STORED fields … a nested engine write from a hook is unsupported in the standalone runtime (the QuickJS hook sandbox crashes on nested writes; ctx.services.data is undefined) …

受影响字段:

模板 字段 现状
expense expense_report.total_amount 存储字段,client/seed 维护
procurement procurement_order.received_amount 存储字段,client/seed 维护
project pm_project.progress_percent / actual_cost 存储字段
content content_publication.total_* flow/存储,非 live
compliance compliance_control.last_status / last_assessed_at 存储字段

平台侧状态(framework)

底层限制已在 framework 侧解决:

  • 崩溃已修复:沙箱早已改为 deferred-promise + pump 的宿主调用模型,嵌套写入不再二次展开 asyncify 栈 → 不再崩溃。
  • framework#3232(评审中)补齐了回归覆盖 + 修掉了钩子超时被硬钳到 250ms 的 declared ≠ enforced 缺口(现可按 spec 声明更大的 timeoutMs,给较深的 rollup 链留预算)。
  • 已用 真实 SQLite(better-sqlite3,落盘) 验证:expense_lineafterInsert/afterUpdate 钩子嵌套写 expense_report.total_amount,insert/update 都正确回填、无崩溃(见 framework#3232 的 nested-write-real-sqlite.integration.test.ts)。

建议的转换路径(待 framework 修复发布 + 本仓 bump @objectstack 后再做)

按聚合类型选对工具:

  1. 可声明的求和/计数/极值 rollup(且需 delete 安全)→ 用原生 summary 字段,而不是钩子。引擎在删除时会自己捕获子记录 FK 的 pre-image 并重算父级;afterDelete 钩子只拿到 { id, options }、拿不到被删行的 FK,天然不适合做删除回滚。适用:expense_report.total_amountprocurement_order.received_amountcontent_publication.total_*
  2. 条件式 / 非聚合的跨对象写入 → 用嵌套写钩子(现已安全)。适用:compliance_control.last_status/last_assessed_at(取最近一次 assessment 的结果)、pm_project 的派生进度。较深的链在钩子 body 里声明更大的 timeoutMs(≤30_000ms)。

验收(遵循本仓 AGENTS.md「build 通过 ≠ 能跑」)

每个模板转换后必须 boot all env 实测:Server is ready + seeded on empty DB + 0 条 ERROR,并确认子记录变更后父级字段实时更新。同时更新对应 CHARTER 的「Rollup vs. lifecycle hooks」段落与 AGENTS.md 的 Runtime gotchas(移除已过时的 #1867 崩溃说明)。

门槛

依赖 framework#1867 的修复正式发布,且本仓把 @objectstack/*^11.2.0 bump 到含修复的版本。在此之前保持现状(现状对所 pin 的已发布运行时是正确的)——不要提前转换,否则会 advertise 一个已发布运行时尚未提供的能力。

关联:framework#1867、framework#3232、framework#3233。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions