L06 参考解:退款成功但响应丢失:可靠执行的核心实验
这是可讨论的参考设计,不是唯一架构。先完成实验题面,再对照本解。
关键推导
核心顺序是先认证/定位提案,再查稳定操作记录:若已确认,比较参数摘要并返回原结果;如果没有记录,才检查当前审批有效性与订单版本,计算业务变更并原子提交。这解释了“新的过期操作要拒绝”与“已完成操作的过期重放可以返回结果”不矛盾。
before_commit故障在事务内抛出异常,ROLLBACK保证账本与余额同时撤销。after_commit在COMMIT之后抛出LostResponse,所以恢复只能读事实,不能从异常推断未执行。
fencing token的作用是阻止过时所有者更新受保护资源;它需要由该资源检查。只在日志里记录token、不在SQL/外部资源处验证,没有安全效果。参考RunLedger证明的是本数据库状态写入;不声称它能阻止所有远程工具副作用。
参考算法与实现位置
BEGIN IMMEDIATE
authorize principal and load proposal
if operation exists:
require same digest
return stored result
require approved AND now < expiry
require order.version == approved_version
recompute policy and remaining amount
conditional update order
insert ledger UNIQUE(tenant,operation_id)
insert operation(digest,result)
mark proposal consumed
COMMIT
远程版本的参考恢复状态:NOT_SENT→SENT_UNKNOWN→CONFIRMED/FAILED;UNKNOWN阶段先查询稳定operation_id,外部既不支持查询也不支持幂等时转人工,不能承诺恰好一次。
应当得到的可检查结果
| 崩溃/重试窗口 | 账本/结果 |
|---|---|
| before_commit | 账本0,余额不变,后续安全重试 |
| after_commit | 调用方LostResponse,账本1 |
| 同参重试after_commit | 返回原CONFIRMED,账本仍1 |
| 同key但不同金额 | IDEMPOTENCY_CONFLICT |
| 新执行时审批已过期 | APPROVAL_EXPIRED,无新增账本 |
| 已完成操作过期后同参查询/重放 | 返回旧结果,无新副作用 |
| 旧worker在新worker接管后写状态 | STALE_WORKER |
| 两个worker同时提交 | 同结果,账本1 |
怎样判断替代实现是否等价
替代实现必须保留题面中的身份来源、状态归属和失败语义。数据库/框架可以更换,但应把相同故障窗口重新跑一遍。只在正常路径输出一致,不足以证明恢复与授权等价。异步或并发实现还必须解释取消传播、竞争窗口和资源回收。
常见错误与修正
第一类错误是把协议或框架提供的局部保证放大成业务保证:格式正确不等于授权,执行结束不等于业务成功,持久化不等于外部副作用恰好一次。修正方式是找到事实源并把不变量放在拥有该事实的层。
第二类错误是用演示数据替代证据。已有fixture可以检查确定性公式与状态机,但真实模型、网络或容器的结论需要实际运行。报告同时写出“已验证”“仅模拟”“未验证”,比宣称全部完成更有工程价值。
实现范围与限制
参考模型是真实SQLite事务测试,不是真实支付系统测试。没有实现Temporal worker或LangGraph运行;框架对照须另行安装、固定版本并跑同一故障矩阵。
开放题评分要点
副作用不变量35;崩溃与并发测试30;参数绑定15;远程不确定性说明10;框架对照10(未选框架则用完整机制对照)。 正确的反例、失败分析和替代方案论证应获得分数;框架堆叠、只报最终成功截图、删除失败成本不应获得同等评价。