LangGraph 03:持久化、Interrupt、恢复与时间旅行
1、本篇任务:让退款流程暂停一天后还能继续
审批可能几秒后完成,也可能第二天才处理。HTTP 请求不能一直挂着,所以图必须保存状态、结束当前请求,并在新请求中从相同 thread 恢复。
2、Checkpoint、Thread、Store 的关系
checkpointer 在每个 super-step 保存 state snapshot;thread ID 把一系列 checkpoint 组织成一次持续运行;store 保存跨 thread 的长期数据。业务订单和审计仍在自己的数据库,不应全部塞进 checkpoint。
from langgraph.checkpoint.memory import InMemorySaver
graph = builder.compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "refund-task-42"}}
内存 saver 仅用于测试。生产数据库需要处理租户隔离、加密、备份、TTL 和 schema 迁移。
3、使用 interrupt 暂停审批
from langgraph.types import interrupt, Command
def approval_node(state: RefundState):
decision = interrupt({
"action_id": state["action_id"],
"kind": "refund",
"order_id": state["order_id"],
"amount": state["refund_amount"],
"expires_at": state["approval_expires_at"],
})
return {"decision": decision["decision"]}
# 第一次运行会暂停并保存 checkpoint
graph.invoke(initial_state, config=config)
# 后续请求使用同一个 thread 恢复
graph.invoke(Command(resume={"decision": "approve"}), config=config)
TypeScript 使用 interrupt(payload) 与 new Command({ resume: decision })。payload 必须 JSON 可序列化;不要在 interrupt() 外包会吞掉中断的宽泛 try/except;不要在节点升级时随意改变多个 interrupt 的顺序。
4、为什么 interrupt 前的代码可能再次执行
恢复时节点会从头重新运行,直到 interrupt() 返回 resume 值。因此 interrupt 前的副作用必须幂等,最好把副作用放在批准之后的独立节点。
正确拆分:
draft_refund(纯计算/保存草案)
→ approval(只 interrupt)
→ validate_decision(重新鉴权、检查 hash/过期)
→ submit_refund(action_id 幂等副作用)
5、恢复 API 的权限合同
浏览器提交 action_id + decision。服务端根据登录态检查:action 属于当前用户/租户;thread 与 action 匹配;仍是 pending;未过期;批准的参数 hash 与草案一致。然后在事务内记录决定并恢复图。
thread ID、checkpoint ID、action ID 都是定位符,不是授权凭证。
6、故障恢复与 pending writes
并发 super-step 中一个节点失败时,已成功节点的 pending writes 可被保存,恢复时无需全部重跑。但外部服务是否重复调用仍由你的工具幂等保障。
重点测试故障窗口:退款服务已经成功,但 worker 在写完成状态前崩溃。恢复后 submit_refund(action_id) 必须返回同一退款记录,不产生第二条。
7、Time travel 是调试与分支,不是删除历史
checkpoint 历史可用于查看旧 state、从某个 snapshot fork 新分支、在隔离环境重放 bug。已经发生的退款、邮件或审计不能靠回到旧 checkpoint 撤销。回放时禁用真实副作用或复用原 action ID。
State schema 变化时为旧 checkpoint 写纯函数迁移,并保留 state_schema_version/graph_version。蓝绿部署期间可让旧 thread 固定由兼容 worker 完成。
8、本篇测试
暂停后进程退出再恢复;错误 thread/用户不能审批;过期和篡改参数被拒绝;重复 resume 不重复退款;interrupt 前节点重复执行仍无副作用;旧 checkpoint 可迁移或进入人工队列。
下一课学习如何把 state、消息、工具和自定义进度流式输出,并在生产环境定位图故障。
官方阅读:Persistence、Interrupts。
如果您觉得这篇文章有帮助,请点个赞吧~
评论
请登录后发表评论
去登录