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!(
125 " - Dependency resolution: {:?}",
126 stats.dependency_resolution_time
127 );
128 println!(" - Configuration: {:?}", stats.configuration_time);
129 println!(" - Initialization: {:?}", stats.initialization_time);
130 println!(" - Boot: {:?}", stats.boot_time);
131 println!("===============================\n");
132 }
133}
134
135impl Default for ModuleLoader {
136 fn default() -> Self {
137 Self::new()
138 }
139}
140
141#[derive(Debug, Clone)]
143pub struct LoadingStats {
144 pub module_count: usize,
145 pub total_time: std::time::Duration,
146 pub validation_time: std::time::Duration,
147 pub dependency_resolution_time: std::time::Duration,
148 pub configuration_time: std::time::Duration,
149 pub initialization_time: std::time::Duration,
150 pub boot_time: std::time::Duration,
151}
152
153impl LoadingStats {
154 pub fn new() -> Self {
156 Self {
157 module_count: 0,
158 total_time: std::time::Duration::ZERO,
159 validation_time: std::time::Duration::ZERO,
160 dependency_resolution_time: std::time::Duration::ZERO,
161 configuration_time: std::time::Duration::ZERO,
162 initialization_time: std::time::Duration::ZERO,
163 boot_time: std::time::Duration::ZERO,
164 }
165 }
166
167 pub fn phase_percentages(&self) -> PhasePercentages {
169 let total_micros = self.total_time.as_micros() as f64;
170
171 if total_micros == 0.0 {
172 return PhasePercentages::default();
173 }
174
175 PhasePercentages {
176 validation: (self.validation_time.as_micros() as f64 / total_micros) * 100.0,
177 dependency_resolution: (self.dependency_resolution_time.as_micros() as f64
178 / total_micros)
179 * 100.0,
180 configuration: (self.configuration_time.as_micros() as f64 / total_micros) * 100.0,
181 initialization: (self.initialization_time.as_micros() as f64 / total_micros) * 100.0,
182 boot: (self.boot_time.as_micros() as f64 / total_micros) * 100.0,
183 }
184 }
185}
186
187impl Default for LoadingStats {
188 fn default() -> Self {
189 Self::new()
190 }
191}
192
193#[derive(Debug, Clone, Default)]
195pub struct PhasePercentages {
196 pub validation: f64,
197 pub dependency_resolution: f64,
198 pub configuration: f64,
199 pub initialization: f64,
200 pub boot: f64,
201}
202
203pub struct ModuleLoaderBuilder {
205 loader: ModuleLoader,
206}
207
208impl ModuleLoaderBuilder {
209 pub fn new() -> Self {
211 Self {
212 loader: ModuleLoader::new(),
213 }
214 }
215
216 pub fn add_module<M: Module + 'static>(mut self, module: M) -> Self {
218 self.loader.register(module);
219 self
220 }
221
222 pub fn add_modules<M: Module + 'static>(mut self, modules: Vec<M>) -> Self {
224 self.loader.register_modules(modules);
225 self
226 }
227
228 pub fn build(self) -> ModuleLoader {
230 self.loader
231 }
232
233 pub async fn load(mut self) -> Result<Container, ModuleError> {
235 self.loader.load().await
236 }
237}
238
239impl Default for ModuleLoaderBuilder {
240 fn default() -> Self {
241 Self::new()
242 }
243}
244
245#[cfg(test)]
246mod tests {
247 use super::*;
248 use crate::modules::BaseModule;
249
250 #[tokio::test]
251 async fn test_module_loader() -> Result<(), ModuleError> {
252 let mut loader = ModuleLoader::new();
253
254 loader.register(BaseModule::new("test_module_1"));
255 loader.register(BaseModule::new("test_module_2"));
256
257 let container = loader.load().await?;
258
259 assert!(container.is_initialized());
260 assert_eq!(loader.loading_stats().module_count, 2);
261
262 Ok(())
263 }
264
265 #[tokio::test]
266 async fn test_module_loader_builder() -> Result<(), ModuleError> {
267 let container = ModuleLoaderBuilder::new()
268 .add_module(BaseModule::new("test_module_1"))
269 .add_module(BaseModule::new("test_module_2"))
270 .load()
271 .await?;
272
273 assert!(container.is_initialized());
274
275 Ok(())
276 }
277}