elif_core/modules/
loader.rs1use crate::container::{Container, ContainerBuilder};
2use crate::modules::{Module, ModuleError, ModuleRegistry};
3use std::time::Instant;
4
5pub struct ModuleLoader {
7 registry: ModuleRegistry,
8 loading_stats: LoadingStats,
9}
10
11impl ModuleLoader {
12 pub fn new() -> Self {
14 Self {
15 registry: ModuleRegistry::new(),
16 loading_stats: LoadingStats::new(),
17 }
18 }
19
20 pub fn with_registry(registry: ModuleRegistry) -> Self {
22 Self {
23 registry,
24 loading_stats: LoadingStats::new(),
25 }
26 }
27
28 pub fn register<M: Module + 'static>(&mut self, module: M) {
30 self.registry.register(module);
31 }
32
33 pub fn register_modules<M: Module + 'static>(&mut self, modules: Vec<M>) {
35 for module in modules {
36 self.registry.register(module);
37 }
38 }
39
40 pub async fn load(&mut self) -> Result<Container, ModuleError> {
42 let start_time = Instant::now();
43
44 tracing::info!("Starting module loading process...");
45
46 self.registry.validate()?;
48 self.loading_stats.validation_time = start_time.elapsed();
49
50 let dep_start = Instant::now();
52 self.registry.resolve_dependencies()?;
53 self.loading_stats.dependency_resolution_time = dep_start.elapsed();
54
55 let config_start = Instant::now();
57 let builder = ContainerBuilder::new();
58 let builder = self.registry.configure_all(builder)?;
59 let mut container = builder.build()?;
60 self.loading_stats.configuration_time = config_start.elapsed();
61
62 let init_start = Instant::now();
64 container.initialize().await?;
65 self.loading_stats.initialization_time = init_start.elapsed();
66
67 let boot_start = Instant::now();
69 self.registry.boot_all(&container)?;
70 self.loading_stats.boot_time = boot_start.elapsed();
71
72 self.loading_stats.total_time = start_time.elapsed();
73 self.loading_stats.module_count = self.registry.module_count();
74
75 tracing::info!(
76 "Module loading completed successfully in {:?} with {} modules",
77 self.loading_stats.total_time,
78 self.loading_stats.module_count
79 );
80
81 Ok(container)
82 }
83
84 pub fn load_modules_only(&mut self) -> Result<(), ModuleError> {
86 self.registry.validate()?;
87 self.registry.resolve_dependencies()?;
88 Ok(())
89 }
90
91 pub fn loading_stats(&self) -> &LoadingStats {
93 &self.loading_stats
94 }
95
96 pub fn registry(&self) -> &ModuleRegistry {
98 &self.registry
99 }
100
101 pub fn registry_mut(&mut self) -> &mut ModuleRegistry {
103 &mut self.registry
104 }
105
106 pub fn routes(&mut self) -> Vec<crate::modules::RouteDefinition> {
108 self.registry.collect_routes()
109 }
110
111 pub fn middleware(&mut self) -> Vec<crate::modules::MiddlewareDefinition> {
113 self.registry.collect_middleware()
114 }
115
116 pub fn print_summary(&self) {
118 let stats = &self.loading_stats;
119
120 println!("\n=== Module Loading Summary ===");
121 println!("Modules loaded: {}", stats.module_count);
122 println!("Total time: {:?}", stats.total_time);
123 println!(" - Validation: {:?}", stats.validation_time);
124 println!(" - Dependency resolution: {:?}", stats.dependency_resolution_time);
125 println!(" - Configuration: {:?}", stats.configuration_time);
126 println!(" - Initialization: {:?}", stats.initialization_time);
127 println!(" - Boot: {:?}", stats.boot_time);
128 println!("===============================\n");
129 }
130}
131
132impl Default for ModuleLoader {
133 fn default() -> Self {
134 Self::new()
135 }
136}
137
138#[derive(Debug, Clone)]
140pub struct LoadingStats {
141 pub module_count: usize,
142 pub total_time: std::time::Duration,
143 pub validation_time: std::time::Duration,
144 pub dependency_resolution_time: std::time::Duration,
145 pub configuration_time: std::time::Duration,
146 pub initialization_time: std::time::Duration,
147 pub boot_time: std::time::Duration,
148}
149
150impl LoadingStats {
151 pub fn new() -> Self {
153 Self {
154 module_count: 0,
155 total_time: std::time::Duration::ZERO,
156 validation_time: std::time::Duration::ZERO,
157 dependency_resolution_time: std::time::Duration::ZERO,
158 configuration_time: std::time::Duration::ZERO,
159 initialization_time: std::time::Duration::ZERO,
160 boot_time: std::time::Duration::ZERO,
161 }
162 }
163
164 pub fn phase_percentages(&self) -> PhasePercentages {
166 let total_micros = self.total_time.as_micros() as f64;
167
168 if total_micros == 0.0 {
169 return PhasePercentages::default();
170 }
171
172 PhasePercentages {
173 validation: (self.validation_time.as_micros() as f64 / total_micros) * 100.0,
174 dependency_resolution: (self.dependency_resolution_time.as_micros() as f64 / total_micros) * 100.0,
175 configuration: (self.configuration_time.as_micros() as f64 / total_micros) * 100.0,
176 initialization: (self.initialization_time.as_micros() as f64 / total_micros) * 100.0,
177 boot: (self.boot_time.as_micros() as f64 / total_micros) * 100.0,
178 }
179 }
180}
181
182impl Default for LoadingStats {
183 fn default() -> Self {
184 Self::new()
185 }
186}
187
188#[derive(Debug, Clone, Default)]
190pub struct PhasePercentages {
191 pub validation: f64,
192 pub dependency_resolution: f64,
193 pub configuration: f64,
194 pub initialization: f64,
195 pub boot: f64,
196}
197
198pub struct ModuleLoaderBuilder {
200 loader: ModuleLoader,
201}
202
203impl ModuleLoaderBuilder {
204 pub fn new() -> Self {
206 Self {
207 loader: ModuleLoader::new(),
208 }
209 }
210
211 pub fn add_module<M: Module + 'static>(mut self, module: M) -> Self {
213 self.loader.register(module);
214 self
215 }
216
217 pub fn add_modules<M: Module + 'static>(mut self, modules: Vec<M>) -> Self {
219 self.loader.register_modules(modules);
220 self
221 }
222
223 pub fn build(self) -> ModuleLoader {
225 self.loader
226 }
227
228 pub async fn load(mut self) -> Result<Container, ModuleError> {
230 self.loader.load().await
231 }
232}
233
234impl Default for ModuleLoaderBuilder {
235 fn default() -> Self {
236 Self::new()
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243 use crate::modules::BaseModule;
244
245 #[tokio::test]
246 async fn test_module_loader() -> Result<(), ModuleError> {
247 let mut loader = ModuleLoader::new();
248
249 loader.register(BaseModule::new("test_module_1"));
250 loader.register(BaseModule::new("test_module_2"));
251
252 let container = loader.load().await?;
253
254 assert!(container.is_initialized());
255 assert_eq!(loader.loading_stats().module_count, 2);
256
257 Ok(())
258 }
259
260 #[tokio::test]
261 async fn test_module_loader_builder() -> Result<(), ModuleError> {
262 let container = ModuleLoaderBuilder::new()
263 .add_module(BaseModule::new("test_module_1"))
264 .add_module(BaseModule::new("test_module_2"))
265 .load()
266 .await?;
267
268 assert!(container.is_initialized());
269
270 Ok(())
271 }
272}