rust_langgraph/channels/
ephemeral.rs1use super::BaseChannel;
6use crate::errors::Result;
7use serde::{Deserialize, Serialize};
8use std::fmt::Debug;
9use std::marker::PhantomData;
10
11#[derive(Debug, Clone)]
31pub struct EphemeralValue<T> {
32 value: Option<T>,
33 _phantom: PhantomData<T>,
34}
35
36impl<T> EphemeralValue<T> {
37 pub fn new() -> Self {
39 Self {
40 value: None,
41 _phantom: PhantomData,
42 }
43 }
44
45 pub fn clear(&mut self) {
47 self.value = None;
48 }
49}
50
51impl<T> Default for EphemeralValue<T> {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57impl<T> BaseChannel for EphemeralValue<T>
58where
59 T: Serialize + for<'de> Deserialize<'de> + Clone + Send + Sync + Debug + 'static,
60{
61 fn get(&self) -> Result<Option<serde_json::Value>> {
62 match &self.value {
63 Some(v) => Ok(Some(serde_json::to_value(v)?)),
64 None => Ok(None),
65 }
66 }
67
68 fn update(&mut self, values: Vec<serde_json::Value>) -> Result<()> {
69 if let Some(last) = values.last() {
71 self.value = Some(serde_json::from_value(last.clone())?);
72 }
73 Ok(())
74 }
75
76 fn checkpoint(&self) -> Result<serde_json::Value> {
77 Ok(serde_json::Value::Null)
79 }
80
81 fn from_checkpoint(_data: serde_json::Value) -> Result<Box<dyn BaseChannel>> {
82 Ok(Box::new(Self::new()))
84 }
85
86 fn type_name(&self) -> &'static str {
87 "EphemeralValue"
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_ephemeral_basic() {
97 let mut channel = EphemeralValue::<i32>::new();
98 assert!(channel.get().unwrap().is_none());
99
100 channel.update(vec![serde_json::json!(42)]).unwrap();
101 assert_eq!(channel.get().unwrap(), Some(serde_json::json!(42)));
102 }
103
104 #[test]
105 fn test_ephemeral_clear() {
106 let mut channel = EphemeralValue::<String>::new();
107 channel.update(vec![serde_json::json!("temporary")]).unwrap();
108 assert!(channel.get().unwrap().is_some());
109
110 channel.clear();
111 assert!(channel.get().unwrap().is_none());
112 }
113
114 #[test]
115 fn test_ephemeral_checkpoint() {
116 let mut channel = EphemeralValue::<i32>::new();
117 channel.update(vec![serde_json::json!(100)]).unwrap();
118
119 let checkpoint = channel.checkpoint().unwrap();
121 assert_eq!(checkpoint, serde_json::Value::Null);
122
123 let restored = EphemeralValue::<i32>::from_checkpoint(checkpoint).unwrap();
125 assert!(restored.get().unwrap().is_none());
126 }
127
128 #[test]
129 fn test_ephemeral_last_write_wins() {
130 let mut channel = EphemeralValue::<i32>::new();
131 channel
132 .update(vec![
133 serde_json::json!(1),
134 serde_json::json!(2),
135 serde_json::json!(3),
136 ])
137 .unwrap();
138
139 assert_eq!(channel.get().unwrap(), Some(serde_json::json!(3)));
140 }
141}