strands_agents/
async_utils.rs1use std::future::Future;
4
5use tokio::runtime::Handle;
6
7pub fn run_async<F, T>(async_func: F) -> T
20where
21 F: Future<Output = T> + Send,
22 T: Send,
23{
24
25 match Handle::try_current() {
26 Ok(_handle) => {
27
28 std::thread::scope(|s| {
29 s.spawn(move || {
30 let rt = tokio::runtime::Builder::new_current_thread()
31 .enable_all()
32 .build()
33 .expect("Failed to create runtime");
34 rt.block_on(async_func)
35 })
36 .join()
37 .expect("Thread panicked")
38 })
39 }
40 Err(_) => {
41
42 let rt = tokio::runtime::Builder::new_current_thread()
43 .enable_all()
44 .build()
45 .expect("Failed to create runtime");
46 rt.block_on(async_func)
47 }
48 }
49}
50
51pub fn spawn_async<F, T>(async_func: F) -> tokio::task::JoinHandle<T>
56where
57 F: Future<Output = T> + Send + 'static,
58 T: Send + 'static,
59{
60 match Handle::try_current() {
61 Ok(handle) => handle.spawn(async_func),
62 Err(_) => panic!("spawn_async must be called from within a tokio runtime"),
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_run_async_simple() {
72 async fn add(a: i32, b: i32) -> i32 {
73 a + b
74 }
75
76 let result = run_async(add(2, 3));
77 assert_eq!(result, 5);
78 }
79
80 #[tokio::test]
81 async fn test_run_async_from_async_context() {
82 async fn multiply(a: i32, b: i32) -> i32 {
83 a * b
84 }
85
86
87 let result = run_async(multiply(4, 5));
88 assert_eq!(result, 20);
89 }
90
91 #[tokio::test]
92 async fn test_spawn_async() {
93 async fn compute() -> String {
94 "hello".to_string()
95 }
96
97 let handle = spawn_async(compute());
98 let result = handle.await.unwrap();
99 assert_eq!(result, "hello");
100 }
101}
102