rohas_runtime/
rust_runtime.rs1use crate::error::{Result, RuntimeError};
2use crate::handler::{HandlerContext, HandlerResult};
3use std::collections::HashMap;
4use std::path::{Path, PathBuf};
5use std::sync::{Arc, Mutex};
6use tokio::sync::RwLock;
7use tracing::{debug, info, warn};
8
9pub struct RustRuntime {
10 handlers: Arc<RwLock<HashMap<String, RustHandlerFn>>>,
11 project_root: Arc<Mutex<Option<PathBuf>>>,
12}
13
14type RustHandlerFn = Box<
15 dyn Fn(HandlerContext) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<HandlerResult>> + Send>> + Send + Sync,
16>;
17
18impl RustRuntime {
19 pub fn new() -> Result<Self> {
20 info!("Rust runtime initialized");
21
22 Ok(Self {
23 handlers: Arc::new(RwLock::new(HashMap::new())),
24 project_root: Arc::new(Mutex::new(None)),
25 })
26 }
27
28 pub fn set_project_root(&mut self, root: PathBuf) {
29 let mut project_root = self.project_root.lock().unwrap();
30 *project_root = Some(root);
31 }
32
33 pub async fn register_handler<F, Fut>(&self, name: String, handler: F)
34 where
35 F: Fn(HandlerContext) -> Fut + Send + Sync + 'static,
36 Fut: std::future::Future<Output = Result<HandlerResult>> + Send + 'static,
37 {
38 let handler_fn: RustHandlerFn = Box::new(move |ctx| {
39 Box::pin(handler(ctx))
40 });
41
42 let mut handlers = self.handlers.write().await;
43 let was_present = handlers.contains_key(&name);
44
45 let handler_ptr = &handler_fn as *const _ as usize;
46 if was_present {
47 if let Some(old_handler) = handlers.get(&name) {
48 let old_ptr = old_handler as *const _ as usize;
49 info!("Re-registering Rust handler: {} (old closure ptr: 0x{:x}, new closure ptr: 0x{:x})", name, old_ptr, handler_ptr);
50 if old_ptr == handler_ptr {
51 warn!("WARNING: Handler closure pointer is the same! This may indicate the handler wasn't actually replaced.");
52 } else {
53 info!("Handler closure pointer changed - old handler should be replaced");
54 }
55 } else {
56 info!("Re-registering Rust handler: {} (new closure ptr: 0x{:x})", name, handler_ptr);
57 }
58 handlers.remove(&name);
59 } else {
60 info!("Registering Rust handler: {} (closure ptr: 0x{:x})", name, handler_ptr);
61 }
62
63 handlers.insert(name.clone(), handler_fn);
64 }
65
66 pub async fn execute_handler(
67 &self,
68 handler_path: &Path,
69 context: HandlerContext,
70 ) -> Result<HandlerResult> {
71 let start = std::time::Instant::now();
72 let handler_name = context.handler_name.clone();
73
74 debug!("Executing Rust handler: {:?}", handler_path);
75
76 {
77 let handlers = self.handlers.read().await;
78 if let Some(handler_fn) = handlers.get(&handler_name) {
79 let closure_ptr = handler_fn as *const _ as usize;
80 debug!("Executing registered Rust handler: {} (closure pointer: 0x{:x})", handler_name, closure_ptr);
81 let result = handler_fn(context).await?;
82 let execution_time_ms = start.elapsed().as_millis() as u64;
83
84 if let Some(data) = &result.data {
85 if let Some(data_str) = data.as_str() {
86 debug!("Handler response snippet: {}...", &data_str[..data_str.len().min(50)]);
87 }
88 }
89
90 return Ok(HandlerResult {
91 execution_time_ms,
92 ..result
93 });
94 }
95 }
96
97 self.execute_handler_from_file(handler_path, context, start).await
98 }
99
100 async fn execute_handler_from_file(
101 &self,
102 handler_path: &Path,
103 context: HandlerContext,
104 start: std::time::Instant,
105 ) -> Result<HandlerResult> {
106 let execution_time_ms = start.elapsed().as_millis() as u64;
107
108 Err(RuntimeError::HandlerNotFound(format!(
109 "Rust handler '{}' not found. To register handlers, call the init_handlers function from your generated project.\n\
110 Example: rust_example::init_handlers(runtime).await\n\
111 Or call: generated::register_all_handlers(runtime).await\n\
112 Handler path: {:?}",
113 context.handler_name,
114 handler_path
115 )))
116 }
117
118 pub async fn handler_count(&self) -> usize {
119 let handlers = self.handlers.read().await;
120 handlers.len()
121 }
122
123 pub async fn list_handlers(&self) -> Vec<String> {
124 let handlers = self.handlers.read().await;
125 handlers.keys().cloned().collect()
126 }
127
128 pub async fn clear_handlers(&self) {
129 let mut handlers = self.handlers.write().await;
130 handlers.clear();
131 info!("Cleared all Rust handlers");
132 }
133}
134
135impl Default for RustRuntime {
136 fn default() -> Self {
137 Self::new().expect("Failed to initialize Rust runtime")
138 }
139}
140
141#[macro_export]
163macro_rules! register_rust_handler {
164 ($runtime:expr, $name:expr, $handler:expr) => {
165 $runtime.register_handler($name.to_string(), $handler).await
166 };
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172 use crate::handler::HandlerContext;
173
174 #[tokio::test]
175 async fn test_rust_runtime_creation() {
176 let runtime = RustRuntime::new().unwrap();
177 assert_eq!(runtime.handler_count().await, 0);
178 }
179
180 #[tokio::test]
181 async fn test_handler_registration() {
182 let runtime = Arc::new(RustRuntime::new().unwrap());
183
184 let handler = |ctx: HandlerContext| async move {
185 Ok(HandlerResult::success(
186 serde_json::json!({"message": "test"}),
187 0,
188 ))
189 };
190
191 runtime
192 .register_handler("test_handler".to_string(), handler)
193 .await;
194
195 assert_eq!(runtime.handler_count().await, 1);
196
197 let handlers = runtime.list_handlers().await;
198 assert_eq!(handlers, vec!["test_handler"]);
199 }
200
201 #[tokio::test]
202 async fn test_handler_execution() {
203 let runtime = Arc::new(RustRuntime::new().unwrap());
204
205 let handler = |ctx: HandlerContext| async move {
206 Ok(HandlerResult::success(
207 serde_json::json!({
208 "handler": ctx.handler_name,
209 "message": "executed"
210 }),
211 0,
212 ))
213 };
214
215 runtime
216 .register_handler("test_exec".to_string(), handler)
217 .await;
218
219 let context = HandlerContext::new("test_exec", serde_json::json!({}));
220 let result = runtime
221 .execute_handler(Path::new("test.rs"), context)
222 .await
223 .unwrap();
224
225 assert!(result.success);
226 assert_eq!(
227 result.data.unwrap()["handler"],
228 serde_json::json!("test_exec")
229 );
230 }
231}
232