问题
recomputeSummaries 在子记录写入成功后重算父对象的 summary 汇总字段时,把每个父记录的 aggregate + update 包在 try/catch 里,失败只打一条 warn 日志——不抛出、不重试、不计入任何面向调用方的结果。
位置:packages/objectql/src/engine.ts(recomputeSummaries,catch 分支)
后果:子记录批量插入返回全部成功,但父记录的汇总值(如发票 total)静默保持过期/缺失。远程 DB(turso)一次网络抖动落在"父汇总 update"上,就得到一笔明细正确、总额错误、无人知晓的数据。seed / import 层的 withTransientRetry 罩不到这里,因为它发生在 engine.insert 内部。
复现(探针测试,可直接作为回归用例)
用 mock 驱动让 update('inv', ...) 第一次抛 fetch failed:
// inv.line_total = summary SUM(inv_line.amount);驱动 update(inv) 首次抛 'fetch failed'consta=awaitengine.insert('inv',{name: 'A'});constres=awaitengine.insert('inv_line',[{name: 'l1',amount: 10,inv: a.id},{name: 'l2',amount: 7,inv: a.id},]);// 实测:res.length === 2(全部报成功),而父记录 line_total === undefined(汇总永远没写上)// 日志仅出现:WARN Roll-up summary recompute failed建议修法
recomputeSummaries 内部对 aggregate + 父 update 加 transient 退避重试(与 @objectstack/core 的 withTransientRetry 同语义)。- 重试耗尽仍失败时,失败必须对调用方可见:抛出,或至少在返回结果/操作上下文中带出"汇总重算失败"信号,不能只 warn。
验收标准
- 父汇总 update 首次抛 transient 错误 → 重试后汇总值正确落库。
- 重试耗尽仍失败 → 调用方能从返回值或异常中感知,不再是静默成功。
- 上述探针场景由红转绿并入正式测试套件。
—— 发现于 #2678 批量写入路径专项测试(测试报告见该 issue 评论)。
问题
recomputeSummaries在子记录写入成功后重算父对象的 summary 汇总字段时,把每个父记录的 aggregate + update 包在 try/catch 里,失败只打一条 warn 日志——不抛出、不重试、不计入任何面向调用方的结果。位置:packages/objectql/src/engine.ts(recomputeSummaries,catch 分支)
后果:子记录批量插入返回全部成功,但父记录的汇总值(如发票
total)静默保持过期/缺失。远程 DB(turso)一次网络抖动落在"父汇总 update"上,就得到一笔明细正确、总额错误、无人知晓的数据。seed / import 层的withTransientRetry罩不到这里,因为它发生在engine.insert内部。复现(探针测试,可直接作为回归用例)
用 mock 驱动让
update('inv', ...)第一次抛fetch failed:建议修法
recomputeSummaries内部对 aggregate + 父 update 加 transient 退避重试(与@objectstack/core的withTransientRetry同语义)。验收标准
—— 发现于 #2678 批量写入路径专项测试(测试报告见该 issue 评论)。