ai_agent/utils/
concurrent.rs1use std::sync::Arc;
7use tokio::sync::Mutex;
8
9pub type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send>>;
11
12pub async fn join_all_concurrent<T, R, F>(items: Vec<T>, f: F) -> Vec<R>
15where
16 T: Send + 'static,
17 R: Send + 'static,
18 F: Fn(T) -> BoxFuture<R> + Send + Clone + 'static,
19{
20 if items.is_empty() {
21 return vec![];
22 }
23
24 let handles: Vec<_> = items
25 .into_iter()
26 .map(|item| {
27 let f = f.clone();
28 tokio::spawn(async move { f(item).await })
29 })
30 .collect();
31
32 let mut results = Vec::with_capacity(handles.len());
33 for handle in handles {
34 if let Ok(result) = handle.await {
35 results.push(result);
36 }
37 }
38 results
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 fn double(x: i32) -> BoxFuture<i32> {
46 Box::pin(async move { x * 2 })
47 }
48
49 #[tokio::test]
50 async fn test_join_all_concurrent() {
51 let items = vec![1, 2, 3];
52 let result = join_all_concurrent(items, double).await;
53 assert_eq!(result, vec![2, 4, 6]);
54 }
55}