11.9 检查点与断点续传
RAF 的检查点(Checkpoint)系统在每轮 SuperStep 完成后自动保存工作流执行状态,支持故障恢复后从断点继续执行。增量/全量混合策略保证了持久化效率和恢复正确性。
检查点架构
flowchart TB
subgraph "执行引擎"
WE[WorkflowEngine]
end
subgraph "检查点管理"
CM[CheckpointManager]
CC[CheckpointConfig]
end
subgraph "存储后端"
FCS[FileCheckpointStore]
ICS[InMemoryCheckpointStore]
end
WE -->|每 SuperStep 后自动 commit| CM
CM --> CC
CM -->|save| FCS
CM -->|save| ICS
CM -->|load / parent链回溯合并| FCS
CM -->|load / parent链回溯合并| ICS
核心类型
Checkpoint — 检查点数据
pub struct Checkpoint {
pub step_number: i32, // 步骤编号(-1 = 初始)
pub graph_fingerprint: String, // 拓扑指纹(恢复时校验)
pub state_data: HashMap<String, serde_json::Value>, // 状态数据
pub edge_state_data: HashMap<String, serde_json::Value>, // 边状态(FanIn 栅栏等)
pub pending_messages: Vec<SerializableMessageEnvelope>, // 未处理消息
pub parent_checkpoint_id: Option<String>, // 父检查点(None = 全量快照)
pub is_full_snapshot: bool,
pub created_at: DateTime<Utc>,
}
CheckpointConfig — 检查点配置
pub struct CheckpointConfig {
pub full_snapshot_interval: u32, // 全量快照间隔(默认 50)
pub max_checkpoints: usize, // 最大保留数(默认 100)
pub enabled: bool, // 是否启用(默认 true)
}
CheckpointInfo — 轻量元数据
pub struct CheckpointInfo {
pub checkpoint_id: String,
pub session_id: String,
pub step_number: i32,
pub parent_checkpoint_id: Option<String>,
pub is_full_snapshot: bool,
pub byte_size: u64,
pub created_at: DateTime<Utc>,
}
增量 + 全量混合策略
sequenceDiagram
participant E as WorkflowEngine
participant CM as CheckpointManager
participant S as ICheckpointStore
loop SuperSteps 1-49
E->>CM: 每步后自动 commit
CM->>CM: 创建增量快照(parent → 前一个)
CM->>S: 仅存储变化的状态数据
end
Note over E,S: Step 50 — 触发全量压缩
E->>CM: commit
CM->>S: 加载所有增量 snapshot
CM->>CM: 合并为全量快照(parent = None)
CM->>S: 存储全量 Checkpoint
CM->>S: 清理旧增量(保留最近 3 个全量链)
- **增量快照**:仅记录变化的状态数据,轻量高效 - **全量快照**:包含完整状态,压缩 parent 链
恢复时从最新检查点沿 parent 链回溯到最近全量快照,合并所有层级的状态。
存储后端
InMemoryCheckpointStore
开发和测试环境:
use rust_agent_workflow::{InMemoryCheckpointStore, CheckpointManager};
let store = Arc::new(InMemoryCheckpointStore::new());
let cp = Arc::new(CheckpointManager::with_default_config(store));
FileCheckpointStore
生产环境持久化,使用原子写入(temp file + rename):
use rust_agent_workflow::{FileCheckpointStore, CheckpointManager};
let store = Arc::new(FileCheckpointStore::new("./checkpoints"));
let cp = Arc::new(CheckpointManager::with_default_config(store));
目录结构:
./checkpoints/
{session_id}/
{checkpoint_id}.json ← 完整检查点数据
{session_id}_index.json ← 元数据索引
循环状态的持久化
循环配置(`LoopOptions`)中的迭代计数作为流程变量存储在 `state_map` 中,自动序列化到 checkpoint。恢复后从断点继续迭代。
// 循环迭代变量格式
let loop_var = loop_options.loop_variable
.unwrap_or_else(|| format!("__loop_{}", node_id));
// 在 state_map 中以 JSON 值存储:json!(current_iteration)
// 恢复时引擎读取该值,从对应迭代继续
使用示例
启用检查点的工作流
use rust_agent_workflow::{
WorkflowBuilder, WorkflowEngine,
CheckpointConfig, CheckpointManager, FileCheckpointStore,
};
let graph = WorkflowBuilder::new()
.add_agent_node("analyze", analyzer)
.add_agent_node("report", reporter)
.set_start("analyze")
.add_edge("analyze", "report")
.with_output_from("report")
.build()?;
let store = Arc::new(FileCheckpointStore::new("./checkpoints"));
let manager = Arc::new(CheckpointManager::with_default_config(store));
let engine = WorkflowEngine::new(graph)
.with_checkpoint_manager(manager);
let session: Arc<dyn ISession> = Arc::new(AgentSession::with_id("workflow-1"));
let (events, outputs) = engine.run(Arc::new(input_messages), Some(session)).await?;
从检查点恢复
let session_id = "workflow-1";
// 加载完整状态
let (latest_checkpoint, merged_state) = manager
.load_full_state(session_id)
.await?
.expect("检查点存在");
// 验证拓扑指纹
if latest_checkpoint.graph_fingerprint != current_fingerprint {
return Err(anyhow!("图结构已变更,无法恢复"));
}
// 重建引擎,从检查点恢复
// 引擎自动恢复 state_map、edge_states 和 pending_messages
ScopeKey — 状态隔离
检查点状态按 `(node_id, scope_name)` 隔离:
pub struct ScopeKey {
pub node_id: String,
pub scope_name: Option<String>, // None = 私有, Some = 共享
}
// 私有作用域:向特定节点可见
ScopeKey::private("node_a");
// 共享作用域:多个节点可读写
ScopeKey::shared("node_a", "shared_context");
// 序列化为字符串键
// 私有: "node_id"
// 共享: "node_id::scope_name"
配置最佳实践
生产环境
let config = CheckpointConfig {
full_snapshot_interval: 20,
max_checkpoints: 200,
enabled: true,
};
开发/测试
let store = Arc::new(InMemoryCheckpointStore::new());
// 或禁用检查点
let config = CheckpointConfig::disabled();
高性能场景
let config = CheckpointConfig {
full_snapshot_interval: 100, // 更大间隔,减少压缩开销
max_checkpoints: 50,
enabled: true,
};
注意事项
1. **图指纹校验**:恢复时校验拓扑指纹,图结构变更则拒绝恢复 2. **多 Session 隔离**:不同 Session 的检查点完全独立 3. **atomic_write**:`FileCheckpointStore` 使用 temp + rename 确保写崩溃安全 4. **自动清理**:超出 `max_checkpoints` 时自动删除最旧的检查点 5. **循环兼容**:循环迭代状态通过 `state_map` 序列化,恢复后正确继续