🏠 总目录📚 本教程 12b · 审批与故障恢复 ← →
📑 本页目录(点开跳转)

12b · 人批了、进程断了:动作到底做没做

⏱ 按故障实践 | 将 Harness 的状态变成可恢复记录

🎯 一句话

超时代表结果未知,不能直接等同于执行失败。 创建工单、退款、发消息这样的动作,恢复前先确认外部状态。

🔗 先读Harness。共同项目的 workflow.py 把草稿、独立审批、执行与对账放进可检查的状态机;测试实际注入提交前后故障。环境见17b。

🔬 先跑一次“工单已创建,但响应丢了”

python examples/knowledge-assistant/lab.py demo
python -m unittest discover -s examples/knowledge-assistant -p test_core.py -v

观察 demo 的恢复结果与工单数量。它先写入模拟外部系统,再故意抛出响应丢失异常;重试按同一业务操作号查询已有工单,最终只有一张。模拟外部系统是一张使用独立事务的表,方便复现“业务副作用与本地确认不能原子提交”的间隙;它不等于已联调真实工单 SaaS。

一、审批绑定的是哪一个动作

待审批草稿身份、内容指纹已审批操作者、到期时间执行中稳定操作号已完成取消 / 审批过期不得发起新的业务动作响应未知:按操作号对账已有结果则确认,未执行才判断重试先查,不盲重发
看右下角的恢复分支:未知状态先查询已有结果;审批过期会阻止新动作,但不应阻止查清已完成的动作。
审批记录 为什么绑定
tenant、请求人、业务对象 防止另一用户拿着 run_id 执行
动作类型与规范化参数指纹 防止批准 50 元后改成 5000 元
审批人身份与 scope 模型不能自己返回一个 approved 就获权
到期时间、状态 旧审批不能无限期重复使用
稳定业务操作号 网络重试仍代表同一笔业务动作

金额用整数分表示,拒绝 bool、NaN、无穷大及非法范围。订单归属、已支付金额、已退款余额从业务库读取,不能相信模型参数。这个原则同样适用于草稿工单的归属与内容。

二、幂等不是一个 try/except

本地先持久化执行意图,调用方使用稳定操作号;模拟下游以唯一约束保证同操作只创建一条记录。相同操作号与相同内容可以回放,不同内容必须冲突。测试同时发起 12 次相同执行,检查只有一张工单。

下游能力 恢复策略 不能声称的保证
支持幂等键与结果查询 同键重发或先查询 幂等键超过保存期后仍永远去重
只支持业务号查询 先查,未知转对账或人工 查询暂未可见就一定没执行
既不支持幂等也无法查询 限制自动重试,人工核对 仅靠本地锁就能端到端 exactly-once

跨系统无法用本地 SQLite 事务包住真实网络副作用。生产可用 outbox 可靠投递意图,用 inbox/下游唯一键去重,再靠状态查询收敛;这仍要求明确下游语义。网络断开、进程退出和超时都是“未知”的来源。

三、故障注入怎样算验收

注入点 必须观察的结果 本项目状态
未批准直接执行 拒绝,工单数为零 已有自动测试
模型冒充审批者 缺审批 scope,拒绝 已有自动测试
审批后修改参数 指纹不符,拒绝 已有自动测试
批准过期且未执行 不再创建工单 已有自动测试
写执行意图后、调用前失败 可用原操作号恢复 已有自动测试
下游创建后响应丢失 查出已有工单,无重复 已有自动测试
响应丢失后审批过期 可对账已有结果,不能发起新动作 已有自动测试
执行前用户取消 后续调用拒绝 已有自动测试
执行中用户取消 返回需对账,不能承诺撤销 代码返回明确状态;真实下游补撤销协议

网络错误只对允许重试的动作采用退避与抖动,遵守 Retry-After 和总预算。权限错误、参数错误、审批失效不应自动重试。对长任务增加租约、心跳和所有权 fencing,避免旧 worker 恢复后与新 worker 同时写;当前单机示例未实现分布式调度。

四、恢复状态不等于恢复授权

恢复时重新读取可信用户身份和业务权限。历史 checkpoint 里保存过角色或 token,不意味着它现在仍有效。不要把原始 bearer token 写入持久化状态;必要凭证从秘密管理系统重新获取,日志只记安全的凭证标识。

审计最少记录 run_id、操作号、状态前后、请求人、审批人、内容指纹、时间、错误类型和下游对象号。记录事实,不记录模型“我已经完成”的自述。按数据保留规则清理正文;删除业务内容与保留必要审计要分别设计。

🛑 现在可以停:能用故障注入解释动作发生了几次,再去接框架的恢复 API。

✅ 检查点

  1. 超时后为什么不能换一个操作号直接重试?
  2. 为什么 checkpoint 中有 approved=true 仍不能执行?
  3. 审批已经过期,是否应该拒绝查询丢失的执行结果?
展开答案
  1. 下游可能已经成功;新号会被视为另一笔动作,产生重复副作用。
  2. 还需要当前身份、资源权限、动作指纹和有效的服务端审批记录。
  3. 不应拒绝对账已有动作;但未发生的动作必须重新满足审批条件。
⚡ 走神救援

审批绑定内容与身份;操作号跨重试保持稳定;未知先对账;checkpoint 不能代替当前授权。

🔗 接下来去哪

➡️ 下一站:16d · LangGraph 实作与运行边界。

打卡记录保存在你的浏览器里,首页能看到总进度