mecha10_runtime/
launcher.rs1use crate::node::NodeRunner;
17use crate::supervisor::{NodeHandle, Supervisor};
18use anyhow::Result;
19use mecha10_core::rwlock_collections::RwLockMapExt;
20use std::collections::HashMap;
21use std::sync::Arc;
22use tokio::sync::RwLock;
23
24pub type NodeFactory = Box<dyn Fn() -> Box<dyn NodeRunner> + Send + Sync>;
26
27pub struct Launcher {
29 supervisor: Arc<Supervisor>,
30 factories: Arc<RwLock<HashMap<String, NodeFactory>>>,
31 running_nodes: Arc<RwLock<HashMap<String, NodeHandle>>>,
32}
33
34impl Launcher {
35 pub fn new(supervisor: Arc<Supervisor>) -> Self {
37 Self {
38 supervisor,
39 factories: Arc::new(RwLock::new(HashMap::new())),
40 running_nodes: Arc::new(RwLock::new(HashMap::new())),
41 }
42 }
43
44 pub async fn register<F>(&self, node_type: String, factory: F)
46 where
47 F: Fn() -> Box<dyn NodeRunner> + Send + Sync + 'static,
48 {
49 let mut factories = self.factories.write().await;
50 factories.insert(node_type, Box::new(factory));
51 }
52
53 pub async fn launch(&self, node_type: &str) -> Result<String> {
55 let factories = self.factories.read().await;
56 let factory = factories
57 .get(node_type)
58 .ok_or_else(|| anyhow::anyhow!("Unknown node type: {}", node_type))?;
59
60 let node = factory();
61 let node_name = node.name().to_string();
62
63 let running = self.running_nodes.read().await;
64 if running.contains_key(&node_name) {
65 anyhow::bail!("Node already running: {}", node_name);
66 }
67 drop(running);
68
69 let handle = self.supervisor.launch_node(node);
70 let name = handle.name().to_string();
71
72 let mut running = self.running_nodes.write().await;
73 running.insert(name.clone(), handle);
74
75 Ok(name)
76 }
77
78 pub async fn stop(&self, node_name: &str) -> Result<()> {
80 let mut running = self.running_nodes.write().await;
81 let handle = running
82 .remove(node_name)
83 .ok_or_else(|| anyhow::anyhow!("Node not running: {}", node_name))?;
84
85 handle.abort();
86 Ok(())
87 }
88
89 pub async fn list_running(&self) -> Vec<String> {
91 let running = self.running_nodes.read().await;
92 running.keys().cloned().collect()
93 }
94
95 pub async fn is_running(&self, node_name: &str) -> bool {
97 let running = self.running_nodes.read().await;
98 running.contains_key(node_name)
99 }
100
101 pub async fn list_types(&self) -> Vec<String> {
103 self.factories.cloned_keys().await
104 }
105}