a↗Agent 工程实战中文课程 / v1.0.0⌕ 搜索课程/
本页目录

L06 退款成功但响应丢失:可靠执行的核心实验

适用章节:M07。本实验允许多种正确实现;验收不变量固定,不强制特定框架。

工程事故

退款服务已经提交账本,Worker在收到响应之前退出。恢复逻辑不知道操作是否发生。如果直接新建请求重试,可能重复退款;如果一概标失败,会向用户谎报并遗漏真实资金变化。

最终交付

带故障注入的幂等业务服务、稳定operation_id、恢复决策表、并发测试;选修LangGraph或Temporal适配与语义对照。

已提供材料

reference/agentlab/business.py、reference/agentlab/durability.py、data/traces/refund_response_lost.json

先独立写出预期行为再看参考解。所有商店、订单、试次与价格单位都是教学构造;不连接真实资金系统。

接口与不可破坏的约束

执行身份与业务意图分开:run_id描述任务,attempt_id描述尝试,operation_id描述同一个业务操作。重试不更换operation_id。幂等键同时绑定规范化参数摘要;同key不同参数拒绝。

本地教学退款把余额、账本、去重结果放在同一SQLite事务内,因此可以检查原子性。对外部支付API,不存在横跨任意网络和数据库的自动原子提交;必须根据外部服务契约设计查询、幂等、对账或人工处理。

实施步骤

  1. 先实现无幂等版本,手推“提交后丢响应”的重复账本风险;不要真的接支付平台。
  2. 在审批前由服务器创建稳定operation_id,摘要绑定订单版本、金额、政策和有效期。
  3. 将业务变更、唯一账本条目与操作结果放在同一事务。
  4. 加入before_commit故障,确认所有写入回滚;加入after_commit故障,确认写入已持久化但调用方看到异常。
  5. 使用同一operation_id恢复;若已完成,授权后返回原结果,即使旧审批现在已过期,也不再次执行。
  6. 启两个独立数据库连接并发重试同一提案;最后必须只出现一笔账本。
  7. 对照Checkpoint、Outbox、幂等、fencing四种机制分别解决的问题。

验收矩阵

崩溃/重试窗口 账本/结果
before_commit 账本0,余额不变,后续安全重试
after_commit 调用方LostResponse,账本1
同参重试after_commit 返回原CONFIRMED,账本仍1
同key但不同金额 IDEMPOTENCY_CONFLICT
新执行时审批已过期 APPROVAL_EXPIRED,无新增账本
已完成操作过期后同参查询/重放 返回旧结果,无新副作用
旧worker在新worker接管后写状态 STALE_WORKER
两个worker同时提交 同结果,账本1

如何运行已有参考测试

在包根目录运行:

python -m unittest discover -s reference/tests -v

本实验主要参考测试类为BusinessTests。已有测试默认验证reference/;测试通过不代表你的starter/实现通过。接入自己的实现时,将被测模块显式替换/注入,保持测试和领域契约不变,不要修改断言来迁就实现。

评分

副作用不变量35;崩溃与并发测试30;参数绑定15;远程不确定性说明10;框架对照10(未选框架则用完整机制对照)。

出现跨租户泄露、未经批准的退款或伪造结果时,不以其他分数抵消。允许记录未完成的选修功能,但必须说明范围。

进阶挑战

使用LangGraph持久节点或Temporal Activity包裹相同业务服务,证明框架恢复仍需要外部幂等。记录节点重启/重放语义,不把继续执行误解为恢复任意Python栈。

提交前自查

保存代码版本、运行命令、输入数据版本、输出日志、失败案例与设计决策。解释至少一个被你否决的方案。没有运行的测试标记“未运行”,不写“预计通过”。参考解见对应答案。