前面学习了graph的基本概念,参数设置,特殊节点和边,今天学习一下检查点
检查点可能名称比较抽象,换个名字可能比较容易理解,进度保存点或者存档点,可以类比游戏中保存当前游戏进度的存档进度
主要用于人工介入的场景,大概流程是每个节点后保存检查点,在某些节点前或后中断,进行人工操作,操作完成后,调用恢复接口resume,graph接收用户输入并根据最近的检查点(存档)恢复执行
可以将其分为存档进度,存档执行流程和存档执行器来了解
存档进度
CheckPoint 类就好比被保存的存档,类中包含一个id(默认自动生成一个uuid),当前节点id nodeId,下一节点id nextNodeId,全局状态 Map<String, Object> state,用后三个字段来记录当前图的执行状态。
存档执行流程
graph会在开始节点记录初始检查点,并且在每个节点执行完毕后更新全局状态时保存检查点,
在中断或异常后,通过调用resume接口来恢复现场,需要再resume接口的RunnableConfig参数中设置checkPointId
每个会话有自己的threadId,不同threadId的检查点会分开管理,确保可以按不同会话来恢复进度
存档器
简单样例
StateGraph graph = ...CompileConfig compileConfig = CompileConfig.builder()
.saverConfig(SaverConfig.builder().type(SaverConstant.FILE).register(SaverConstant.FILE, saver).build()).build();CompiledGraph app = graph.compile(compileConfig);
存档器的设置
在前面参数设置章节有提到过,主要是在编译图时通过CompileConfig设置
CompileConfig 中包含 SaverConfig
SaverConfig中包含一个Map<String, BaseCheckpointSaver>类型的savers属性
SaverConfig提供一个register方法来注册存档器,注册的存档器会放到savers中
SaverConfig还包含一个String类型的type字段
当调用SaverConfig的无参get方法时,取savers.get(type),即savers中key为type对应值的存档器,所以type可以理解为默认存档器的key
存档器的实现类
MemorySaver:基于内存的存档器,断电后存档消失
FileSystemSaver:基于文件系统的存档器
MongoSaver:基于mongodb的存档器
RedisSaver:基于redis的存档器
VersionedMemorySaver:带版本的内存存档器,适合一个会话多次执行图的情况,每次在图的结束节点会将检查点移入历史版本
存档器内部工作原理
以MemorySaver为例了解一下Saver的内部工作原理
MemorySaver内部包含一个 Map<String, LinkedList<Checkpoint>> 类型的属性,key为threadId,值为每个节点后保存的检查点
MemorySaver实现了BaseCheckpointSaver接口,提供get、put、list、clear、release、getLast等方法
调用 put 方法时若 RunnableConfig 的 checkPointId 为空,则直接存入当前检查点,并更新 RunnableConfig 中的 checkPointId;若非空,则替换相同checkPointId的检查点(实际由于更新后的RunnableConfig被丢弃,所以checkPointId一直都是空)
调用 get 方法时若 RunnableConfig 的 checkPointId 为空,则取链表中第一条记录(最新记录);若不为空,则取对应id的 CheckPoint