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>;
25
26pub struct Launcher {
27 supervisor: Arc<Supervisor>,
28 factories: Arc<RwLock<HashMap<String, NodeFactory>>>,
29 running_nodes: Arc<RwLock<HashMap<String, NodeHandle>>>,
30}
31
32impl Launcher {
33 pub fn new(supervisor: Arc<Supervisor>) -> Self {
35 Self {
36 supervisor,
37 factories: Arc::new(RwLock::new(HashMap::new())),
38 running_nodes: Arc::new(RwLock::new(HashMap::new())),
39 }
40 }
41
42 pub async fn register<F>(&self, node_type: String, factory: F)
44 where
45 F: Fn() -> Box<dyn NodeRunner> + Send + Sync + 'static,
46 {
47 let mut factories = self.factories.write().await;
48 factories.insert(node_type, Box::new(factory));
49 }
50
51 pub async fn launch(&self, node_type: &str) -> Result<String> {
53 let factories = self.factories.read().await;
54 let factory = factories
55 .get(node_type)
56 .ok_or_else(|| anyhow::anyhow!("Unknown node type: {}", node_type))?;
57
58 let node = factory();
59 let node_name = node.name().to_string();
60
61 let running = self.running_nodes.read().await;
62 if running.contains_key(&node_name) {
63 anyhow::bail!("Node already running: {}", node_name);
64 }
65 drop(running);
66
67 let handle = self.supervisor.launch_node(node);
68 let name = handle.name().to_string();
69
70 let mut running = self.running_nodes.write().await;
71 running.insert(name.clone(), handle);
72
73 Ok(name)
74 }
75
76 pub async fn stop(&self, node_name: &str) -> Result<()> {
78 let mut running = self.running_nodes.write().await;
79 let handle = running
80 .remove(node_name)
81 .ok_or_else(|| anyhow::anyhow!("Node not running: {}", node_name))?;
82
83 handle.abort();
84 Ok(())
85 }
86
87 pub async fn list_running(&self) -> Vec<String> {
89 let running = self.running_nodes.read().await;
90 running.keys().cloned().collect()
91 }
92
93 pub async fn is_running(&self, node_name: &str) -> bool {
95 let running = self.running_nodes.read().await;
96 running.contains_key(node_name)
97 }
98
99 pub async fn list_types(&self) -> Vec<String> {
101 self.factories.cloned_keys().await
102 }
103}