blvm_sdk/composition/
composer.rs1use crate::composition::config::NodeConfig;
6use crate::composition::lifecycle::ModuleLifecycle;
7use crate::composition::registry::ModuleRegistry;
8use crate::composition::schema::validate_config_schema;
9use crate::composition::types::*;
10use crate::composition::validation::validate_composition;
11use std::path::Path;
12
13pub struct NodeComposer {
15 lifecycle: ModuleLifecycle,
17}
18
19impl NodeComposer {
20 pub fn new<P: AsRef<Path>>(modules_dir: P) -> Self {
22 let registry = ModuleRegistry::new(modules_dir);
23 let lifecycle = ModuleLifecycle::new(registry);
24
25 Self { lifecycle }
26 }
27
28 pub async fn compose_from_config<P: AsRef<Path>>(
30 &mut self,
31 config_path: P,
32 ) -> Result<ComposedNode> {
33 let config = NodeConfig::from_file(config_path)?;
35
36 let schema_validation = validate_config_schema(&config)?;
38 if !schema_validation.valid {
39 return Err(CompositionError::ValidationFailed(format!(
40 "Schema validation failed: {:?}",
41 schema_validation.errors
42 )));
43 }
44
45 let spec = config.to_spec()?;
47
48 self.compose_node(spec).await
50 }
51
52 pub async fn compose_node(&mut self, spec: NodeSpec) -> Result<ComposedNode> {
54 let validation = self.validate_composition(&spec)?;
56 if !validation.valid {
57 return Err(CompositionError::ValidationFailed(format!(
58 "Composition validation failed: {:?}",
59 validation.errors
60 )));
61 }
62
63 let mut loaded_modules = Vec::new();
65 for module_spec in &spec.modules {
66 if !module_spec.enabled {
67 continue;
68 }
69
70 let info = self
71 .lifecycle
72 .registry
73 .get_module(&module_spec.name, module_spec.version.as_deref())?;
74
75 self.lifecycle_mut()
77 .start_module(&info.name, Some(&module_spec.config))
78 .await?;
79 let status = self.lifecycle().get_module_status(&info.name).await?;
80 let health = self.lifecycle().health_check(&info.name).await?;
81
82 loaded_modules.push(LoadedModule {
83 info,
84 status,
85 health,
86 });
87 }
88
89 Ok(ComposedNode {
90 spec,
91 modules: loaded_modules,
92 status: NodeStatus::Running,
93 })
94 }
95
96 pub fn validate_composition(&self, spec: &NodeSpec) -> Result<ValidationResult> {
98 validate_composition(spec, &self.lifecycle.registry)
99 }
100
101 pub fn generate_config(&self) -> String {
103 let config = NodeConfig::template();
104 toml::to_string_pretty(&config)
105 .unwrap_or_else(|_| "# Error generating config template".to_string())
106 }
107
108 pub fn registry(&self) -> &ModuleRegistry {
110 &self.lifecycle.registry
111 }
112
113 pub fn registry_mut(&mut self) -> &mut ModuleRegistry {
115 &mut self.lifecycle.registry
116 }
117
118 pub fn lifecycle(&self) -> &ModuleLifecycle {
120 &self.lifecycle
121 }
122
123 pub fn lifecycle_mut(&mut self) -> &mut ModuleLifecycle {
125 &mut self.lifecycle
126 }
127}