1use pocketflow_core::*;
2use std::collections::HashMap;
3use std::sync::Arc;
4
5type AsyncNodeFunc = Arc<
6 dyn Fn(&mut (dyn std::any::Any + Send), &Params) -> Result<Option<String>> + Send + Sync,
7>;
8
9#[derive(Clone)]
10pub struct AsyncNode {
11 name: String,
12 params: Params,
13 successors: HashMap<String, AsyncNode>,
14 func: AsyncNodeFunc,
15}
16
17impl AsyncNode {
18 pub fn new<F>(name: impl Into<String>, func: F) -> Self
19 where
20 F: Fn(&mut (dyn std::any::Any + Send), &Params) -> Result<Option<String>>
21 + Send
22 + Sync
23 + 'static,
24 {
25 Self {
26 name: name.into(),
27 params: Params::new(),
28 successors: HashMap::new(),
29 func: Arc::new(func),
30 }
31 }
32
33 pub fn add_successor(&mut self, action: impl Into<String>, node: AsyncNode) -> &mut Self {
34 self.successors.insert(action.into(), node);
35 self
36 }
37
38 pub fn next(&mut self, node: AsyncNode) -> &mut Self {
39 self.add_successor("default", node)
40 }
41
42 pub fn set_params(&mut self, params: Params) {
43 self.params = params;
44 }
45
46 pub fn get_params(&self) -> &Params {
47 &self.params
48 }
49
50 pub fn get_successor(&self, action: &str) -> Option<&AsyncNode> {
51 self.successors.get(action)
52 }
53
54 pub fn has_successors(&self) -> bool {
55 !self.successors.is_empty()
56 }
57
58 pub async fn run(&self, shared: &mut (dyn std::any::Any + Send)) -> Result<()> {
59 if self.has_successors() {
60 eprintln!("Warning: AsyncNode won't run successors. Use AsyncFlow.");
61 }
62
63 (self.func)(shared, &self.params)?;
64 Ok(())
65 }
66
67 pub async fn run_recursive(&self, shared: &mut (dyn std::any::Any + Send)) -> Result<()> {
68 let action = (self.func)(shared, &self.params)?;
69
70 if let Some(next_node) = action
71 .as_ref()
72 .and_then(|a| self.successors.get(a))
73 .or_else(|| self.successors.get("default")) {
74 Box::pin(next_node.run_recursive(shared)).await?;
75 }
76
77 Ok(())
78 }
79}
80
81#[derive(Clone)]
82pub struct AsyncFlow {
83 start_node: Option<AsyncNode>,
84 params: Params,
85}
86
87impl AsyncFlow {
88 pub fn new() -> Self {
89 Self {
90 start_node: None,
91 params: Params::new(),
92 }
93 }
94
95 pub fn start(mut self, node: AsyncNode) -> Self {
96 self.start_node = Some(node);
97 self
98 }
99
100 pub fn set_params(&mut self, params: Params) {
101 self.params = params;
102 }
103
104 pub async fn run(&self, shared: &mut (dyn std::any::Any + Send)) -> Result<()> {
105 if let Some(ref node) = self.start_node {
106 let mut node = node.clone();
107 node.set_params(self.params.clone());
108 node.run_recursive(shared).await?;
109 }
110 Ok(())
111 }
112
113 pub async fn run_with_params(&self, shared: &mut (dyn std::any::Any + Send), params: Params) -> Result<()> {
114 if let Some(ref node) = self.start_node {
115 let mut node = node.clone();
116 let mut merged_params = self.params.clone();
117 merged_params.merge(¶ms);
118 node.set_params(merged_params);
119 node.run_recursive(shared).await?;
120 }
121 Ok(())
122 }
123}
124
125impl Default for AsyncFlow {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131#[derive(Clone)]
132pub struct AsyncBatchFlow {
133 start_node: Option<AsyncNode>,
134 params: Params,
135}
136
137impl AsyncBatchFlow {
138 pub fn new() -> Self {
139 Self {
140 start_node: None,
141 params: Params::new(),
142 }
143 }
144
145 pub fn start(mut self, node: AsyncNode) -> Self {
146 self.start_node = Some(node);
147 self
148 }
149
150 pub fn set_params(&mut self, params: Params) {
151 self.params = params;
152 }
153
154 pub async fn run_batch(&self, shared: &mut (dyn std::any::Any + Send), batch_params: Vec<Params>) -> Result<Vec<()>> {
155 let mut results = Vec::with_capacity(batch_params.len());
156 for params in batch_params {
157 let flow = AsyncFlow {
158 start_node: self.start_node.clone(),
159 params: self.params.clone(),
160 };
161 flow.run_with_params(shared, params).await?;
162 results.push(());
163 }
164 Ok(results)
165 }
166}
167
168impl Default for AsyncBatchFlow {
169 fn default() -> Self {
170 Self::new()
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177 use std::sync::{Arc, Mutex};
178
179 #[derive(Default, Clone)]
180 struct TestShared {
181 pub counter: Arc<Mutex<i32>>,
182 }
183
184 #[tokio::test]
185 async fn test_async_flow_execution() {
186 let mut shared = TestShared::default();
187
188 let node = AsyncNode::new("test", |shared, _params| {
189 if let Some(shared) = shared.downcast_mut::<TestShared>() {
190 let mut counter = shared.counter.lock().unwrap();
191 *counter += 1;
192 }
193 Ok(None)
194 });
195
196 let flow = AsyncFlow::new().start(node);
197
198 flow.run(&mut shared).await.unwrap();
199
200 let counter = shared.counter.lock().unwrap();
201 assert_eq!(*counter, 1);
202 }
203
204 #[tokio::test]
205 async fn test_async_chained_flow() {
206 let mut shared = TestShared::default();
207
208 let mut node1 = AsyncNode::new("node1", |shared, _params| {
209 if let Some(shared) = shared.downcast_mut::<TestShared>() {
210 let mut counter = shared.counter.lock().unwrap();
211 *counter += 1;
212 }
213 Ok(None)
214 });
215
216 let node2 = AsyncNode::new("node2", |shared, _params| {
217 if let Some(shared) = shared.downcast_mut::<TestShared>() {
218 let mut counter = shared.counter.lock().unwrap();
219 *counter += 10;
220 }
221 Ok(None)
222 });
223
224 node1.next(node2);
225 let flow = AsyncFlow::new().start(node1);
226
227 flow.run(&mut shared).await.unwrap();
228
229 let counter = shared.counter.lock().unwrap();
230 assert_eq!(*counter, 11);
231 }
232}