synaptic_graph/
checkpoint.rs1use std::collections::HashMap;
2
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use synaptic_core::SynapticError;
6
7#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
9pub struct CheckpointConfig {
10 pub thread_id: String,
11 pub checkpoint_id: Option<String>,
14}
15
16impl CheckpointConfig {
17 pub fn new(thread_id: impl Into<String>) -> Self {
18 Self {
19 thread_id: thread_id.into(),
20 checkpoint_id: None,
21 }
22 }
23
24 pub fn with_checkpoint_id(
26 thread_id: impl Into<String>,
27 checkpoint_id: impl Into<String>,
28 ) -> Self {
29 Self {
30 thread_id: thread_id.into(),
31 checkpoint_id: Some(checkpoint_id.into()),
32 }
33 }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct Checkpoint {
39 pub id: String,
41 pub state: serde_json::Value,
43 pub next_node: Option<String>,
45 pub parent_id: Option<String>,
47 pub metadata: HashMap<String, serde_json::Value>,
49}
50
51impl Checkpoint {
52 pub fn new(state: serde_json::Value, next_node: Option<String>) -> Self {
54 Self {
55 id: generate_checkpoint_id(),
56 state,
57 next_node,
58 parent_id: None,
59 metadata: HashMap::new(),
60 }
61 }
62
63 pub fn with_parent(mut self, parent_id: impl Into<String>) -> Self {
65 self.parent_id = Some(parent_id.into());
66 self
67 }
68
69 pub fn with_metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
71 self.metadata.insert(key.into(), value);
72 self
73 }
74}
75
76fn generate_checkpoint_id() -> String {
77 use std::sync::atomic::{AtomicU64, Ordering};
78 use std::time::{SystemTime, UNIX_EPOCH};
79
80 static COUNTER: AtomicU64 = AtomicU64::new(0);
81
82 let ts = SystemTime::now()
83 .duration_since(UNIX_EPOCH)
84 .unwrap_or_default()
85 .as_nanos();
86 let seq = COUNTER.fetch_add(1, Ordering::Relaxed);
87 format!("{ts:x}-{seq:04x}")
88}
89
90#[async_trait]
92pub trait Checkpointer: Send + Sync {
93 async fn put(
95 &self,
96 config: &CheckpointConfig,
97 checkpoint: &Checkpoint,
98 ) -> Result<(), SynapticError>;
99
100 async fn get(&self, config: &CheckpointConfig) -> Result<Option<Checkpoint>, SynapticError>;
103
104 async fn list(&self, config: &CheckpointConfig) -> Result<Vec<Checkpoint>, SynapticError>;
106}