nerve/integration/
plugin_integration.rs

1//! Plugin-Based System Integration for Nerve Framework
2//!
3//! Provides a plugin-based integration system that dynamically loads components
4//! from separate packages using the plugin system architecture.
5
6use nerve_core_errors::NerveResult;
7use nerve_core_traits::{
8    NerveComponent, NervePlugin,
9};
10use nerve_core_types::{
11    ComponentType, SystemStatistics,
12};
13use nerve_plugin_system::PluginManager;
14use std::sync::Arc;
15
16use crate::integration::plugin_adapters::{
17    CommunicationComponentAdapter, MemoryComponentAdapter, NodeComponentAdapter, ThreadComponentAdapter,
18};
19use crate::integration::plugin_traits::{
20    PluginCommunicationComponent, PluginMemoryComponent, PluginNodeComponent, PluginThreadComponent,
21};
22
23/// Plugin-based system integration structure
24///
25/// This system uses the plugin manager to dynamically load and manage
26/// all Nerve Framework components as separate packages.
27pub struct PluginNerveSystem {
28    /// Plugin manager for dynamic component loading
29    plugin_manager: Arc<PluginManager>,
30    /// System configuration
31    config: SystemConfig,
32    /// Loaded memory component
33    memory_component: Option<Arc<dyn PluginMemoryComponent>>,
34    /// Loaded thread component
35    thread_component: Option<Arc<dyn PluginThreadComponent>>,
36    /// Loaded node component
37    node_component: Option<Arc<dyn PluginNodeComponent>>,
38    /// Loaded communication component
39    communication_component: Option<Arc<dyn PluginCommunicationComponent>>,
40}
41
42/// System configuration for plugin-based integration
43#[derive(Debug, Clone)]
44pub struct SystemConfig {
45    /// Maximum memory usage in bytes
46    pub max_memory_bytes: u64,
47    /// Maximum number of threads
48    pub max_threads: usize,
49    /// Maximum message queue size
50    pub max_queue_size: usize,
51    /// Performance monitoring enabled
52    pub performance_monitoring: bool,
53    /// Plugin loading strategy
54    pub plugin_loading_strategy: PluginLoadingStrategy,
55}
56
57/// Plugin loading strategy
58#[derive(Debug, Clone)]
59pub enum PluginLoadingStrategy {
60    /// Load all available plugins
61    LoadAll,
62    /// Load only specified component types
63    LoadSpecific(Vec<ComponentType>),
64    /// Lazy loading - load plugins on demand
65    LazyLoad,
66}
67
68impl Default for SystemConfig {
69    fn default() -> Self {
70        Self {
71            max_memory_bytes: 1_000_000_000, // 1GB
72            max_threads: 16,
73            max_queue_size: 10_000,
74            performance_monitoring: true,
75            plugin_loading_strategy: PluginLoadingStrategy::LoadAll,
76        }
77    }
78}
79
80impl PluginNerveSystem {
81    /// Create a new plugin-based Nerve System with default configuration
82    pub fn new() -> NerveResult<Self> {
83        Self::with_config(SystemConfig::default())
84    }
85
86    /// Create a new plugin-based Nerve System with custom configuration
87    pub fn with_config(config: SystemConfig) -> NerveResult<Self> {
88        // Validate configuration
89        if config.max_memory_bytes == 0 {
90            return Err(nerve_core_errors::NerveError::Configuration(
91                "Maximum memory bytes must be greater than 0".to_string(),
92            ));
93        }
94
95        if config.max_threads == 0 {
96            return Err(nerve_core_errors::NerveError::Configuration(
97                "Maximum threads must be greater than 0".to_string(),
98            ));
99        }
100
101        if config.max_queue_size == 0 {
102            return Err(nerve_core_errors::NerveError::Configuration(
103                "Maximum queue size must be greater than 0".to_string(),
104            ));
105        }
106
107        // Create plugin manager
108        let plugin_manager = Arc::new(PluginManager::new());
109
110        Ok(Self {
111            plugin_manager,
112            config,
113            memory_component: None,
114            thread_component: None,
115            node_component: None,
116            communication_component: None,
117        })
118    }
119
120    /// Load all required plugins based on configuration
121    pub fn load_plugins(&mut self) -> NerveResult<()> {
122        println!("Loading plugins with strategy: {:?}", self.config.plugin_loading_strategy);
123
124        // Extract the strategy to avoid borrowing issues
125        let strategy = self.config.plugin_loading_strategy.clone();
126
127        match strategy {
128            PluginLoadingStrategy::LoadAll => {
129                self.load_memory_plugin()?;
130                self.load_thread_plugin()?;
131                self.load_node_plugin()?;
132                self.load_communication_plugin()?;
133            }
134            PluginLoadingStrategy::LoadSpecific(types) => {
135                for component_type in types {
136                    match component_type {
137                        ComponentType::Memory => self.load_memory_plugin()?,
138                        ComponentType::Thread => self.load_thread_plugin()?,
139                        ComponentType::Node => self.load_node_plugin()?,
140                        ComponentType::Communication => self.load_communication_plugin()?,
141                        ComponentType::QoS | ComponentType::Integration => {
142                            // These component types are not yet implemented in plugin system
143                            println!("⚠️  Component type {:?} not yet supported in plugin system", component_type);
144                        }
145                    }
146                }
147            }
148            PluginLoadingStrategy::LazyLoad => {
149                // Don't load any plugins initially - they'll be loaded on demand
150                println!("Lazy loading enabled - plugins will be loaded on demand");
151            }
152        }
153
154        println!("Plugin loading completed successfully");
155        Ok(())
156    }
157
158    /// Load memory plugin
159    fn load_memory_plugin(&mut self) -> NerveResult<()> {
160        use nerve_memory::{MemoryManager, MemoryPlugin};
161
162        // Create and load the plugin
163        let plugin = Arc::new(MemoryPlugin::new(self.config.max_memory_bytes));
164        self.plugin_manager.load_plugin(plugin.clone())?;
165
166        // Create adapter for the memory component
167        let memory_manager = Arc::new(MemoryManager::new(self.config.max_memory_bytes));
168        let adapter = Arc::new(MemoryComponentAdapter::new(memory_manager));
169
170        // Store the memory component for direct access
171        self.memory_component = Some(adapter);
172
173        println!("✅ Memory plugin loaded successfully");
174        Ok(())
175    }
176
177    /// Load thread plugin
178    fn load_thread_plugin(&mut self) -> NerveResult<()> {
179        use nerve_thread::{ThreadManager, ThreadPlugin};
180
181        // Create and load the plugin
182        let plugin = Arc::new(ThreadPlugin::new(self.config.max_threads));
183        self.plugin_manager.load_plugin(plugin.clone())?;
184
185        // Create adapter for the thread component
186        let thread_manager = Arc::new(ThreadManager::new(self.config.max_threads));
187        let adapter = Arc::new(ThreadComponentAdapter::new(thread_manager));
188
189        // Store the thread component for direct access
190        self.thread_component = Some(adapter);
191
192        println!("✅ Thread plugin loaded successfully");
193        Ok(())
194    }
195
196    /// Load node plugin
197    fn load_node_plugin(&mut self) -> NerveResult<()> {
198        use nerve_node::{NodeManager, NodePlugin};
199
200        // Create and load the plugin
201        let plugin = Arc::new(NodePlugin::new());
202        self.plugin_manager.load_plugin(plugin.clone())?;
203
204        // Create adapter for the node component
205        let node_manager = Arc::new(NodeManager::new());
206        let adapter = Arc::new(NodeComponentAdapter::new(node_manager));
207
208        // Store the node component for direct access
209        self.node_component = Some(adapter);
210
211        println!("✅ Node plugin loaded successfully");
212        Ok(())
213    }
214
215    /// Load communication plugin
216    fn load_communication_plugin(&mut self) -> NerveResult<()> {
217        use nerve_communication::{CommunicationManager, CommunicationPlugin};
218
219        // Create and load the plugin
220        let plugin = Arc::new(CommunicationPlugin::new());
221        self.plugin_manager.load_plugin(plugin.clone())?;
222
223        // Create adapter for the communication component
224        let communication_manager = Arc::new(CommunicationManager::new());
225        let adapter = Arc::new(CommunicationComponentAdapter::new(communication_manager));
226
227        // Store the communication component for direct access
228        self.communication_component = Some(adapter);
229
230        println!("✅ Communication plugin loaded successfully");
231        Ok(())
232    }
233
234    /// Get memory component (load if necessary)
235    pub fn memory_component(&mut self) -> NerveResult<&Arc<dyn PluginMemoryComponent>> {
236        if self.memory_component.is_none() {
237            self.load_memory_plugin()?;
238        }
239        self.memory_component
240            .as_ref()
241            .ok_or_else(|| nerve_core_errors::NerveError::Component {
242                component_type: nerve_core_types::ComponentType::Memory,
243                message: "Memory component not available".to_string(),
244            })
245    }
246
247    /// Get thread component (load if necessary)
248    pub fn thread_component(&mut self) -> NerveResult<&Arc<dyn PluginThreadComponent>> {
249        if self.thread_component.is_none() {
250            self.load_thread_plugin()?;
251        }
252        self.thread_component
253            .as_ref()
254            .ok_or_else(|| nerve_core_errors::NerveError::Component {
255                component_type: nerve_core_types::ComponentType::Thread,
256                message: "Thread component not available".to_string(),
257            })
258    }
259
260    /// Get node component (load if necessary)
261    pub fn node_component(&mut self) -> NerveResult<&Arc<dyn PluginNodeComponent>> {
262        if self.node_component.is_none() {
263            self.load_node_plugin()?;
264        }
265        self.node_component
266            .as_ref()
267            .ok_or_else(|| nerve_core_errors::NerveError::Component {
268                component_type: nerve_core_types::ComponentType::Node,
269                message: "Node component not available".to_string(),
270            })
271    }
272
273    /// Get communication component (load if necessary)
274    pub fn communication_component(&mut self) -> NerveResult<&Arc<dyn PluginCommunicationComponent>> {
275        if self.communication_component.is_none() {
276            self.load_communication_plugin()?;
277        }
278        self.communication_component
279            .as_ref()
280            .ok_or_else(|| nerve_core_errors::NerveError::Component {
281                component_type: nerve_core_types::ComponentType::Communication,
282                message: "Communication component not available".to_string(),
283            })
284    }
285
286    /// Get plugin manager reference
287    pub fn plugin_manager(&self) -> &Arc<PluginManager> {
288        &self.plugin_manager
289    }
290
291    /// Get system configuration
292    pub fn config(&self) -> &SystemConfig {
293        &self.config
294    }
295
296    /// Check if system is healthy
297    pub fn is_healthy(&self) -> bool {
298        self.plugin_manager.system_health()
299    }
300
301    /// Get system health status
302    pub fn health_status(&self) -> String {
303        if self.is_healthy() {
304            "Healthy".to_string()
305        } else {
306            "Unhealthy".to_string()
307        }
308    }
309
310    /// Get system statistics
311    pub fn get_statistics(&self) -> SystemStatistics {
312        let mut combined_stats = SystemStatistics::default();
313
314        // Combine statistics from all loaded plugins
315        for plugin in self.plugin_manager.get_all_plugins() {
316            let plugin_stats = plugin.get_statistics();
317            combined_stats.messages_processed += plugin_stats.messages_processed;
318            combined_stats.errors_encountered += plugin_stats.errors_encountered;
319            // Add other statistics fields as needed
320        }
321
322        combined_stats
323    }
324
325    /// Get loaded plugin types
326    pub fn loaded_plugin_types(&self) -> Vec<ComponentType> {
327        self.plugin_manager.get_loaded_plugin_types()
328    }
329
330    /// Get plugin count
331    pub fn plugin_count(&self) -> usize {
332        self.plugin_manager.get_all_plugins().len()
333    }
334
335    /// Demonstrate plugin-based message processing
336    pub fn process_message(&mut self, topic: &str, payload: Vec<u8>) -> NerveResult<()> {
337        println!("Processing message via plugin system...");
338
339        // Step 1: Use memory component for allocation
340        let memory_component = self.memory_component()?;
341        println!("  Memory component: {} (healthy: {})",
342            memory_component.id().name,
343            memory_component.is_healthy()
344        );
345
346        // Step 2: Use communication component for message handling
347        let communication_component = self.communication_component()?;
348        println!("  Communication component: {} (healthy: {})",
349            communication_component.id().name,
350            communication_component.is_healthy()
351        );
352
353        // Step 3: Use thread component for coordination
354        let thread_component = self.thread_component()?;
355        println!("  Thread component: {} (healthy: {})",
356            thread_component.id().name,
357            thread_component.is_healthy()
358        );
359
360        // Step 4: Use node component for registration
361        let node_component = self.node_component()?;
362        println!("  Node component: {} (healthy: {})",
363            node_component.id().name,
364            node_component.is_healthy()
365        );
366
367        println!("  Message processed successfully via plugin system");
368        println!("  Topic: {}, Payload size: {} bytes", topic, payload.len());
369
370        Ok(())
371    }
372
373    /// Shutdown the plugin-based system gracefully
374    pub fn shutdown(self) -> NerveResult<()> {
375        println!("🔄 Starting plugin-based system shutdown...");
376
377        // Plugin manager automatically handles plugin shutdown
378        println!("✅ Plugin-based system shutdown complete");
379
380        Ok(())
381    }
382}
383
384impl Default for PluginNerveSystem {
385    fn default() -> Self {
386        Self::new().expect("Failed to create default PluginNerveSystem")
387    }
388}
389
390#[cfg(test)]
391mod tests {
392    use super::*;
393
394    #[test]
395    fn test_plugin_nerve_system_creation() {
396        let system = PluginNerveSystem::new();
397        assert!(system.is_ok());
398
399        let mut system = system.unwrap();
400        assert!(system.is_healthy());
401    }
402
403    #[test]
404    fn test_plugin_nerve_system_with_config() {
405        let config = SystemConfig {
406            max_memory_bytes: 500_000_000,
407            max_threads: 8,
408            max_queue_size: 5_000,
409            performance_monitoring: true,
410            plugin_loading_strategy: PluginLoadingStrategy::LoadAll,
411        };
412
413        let system = PluginNerveSystem::with_config(config);
414        assert!(system.is_ok());
415
416        let system = system.unwrap();
417        assert_eq!(system.config().max_memory_bytes, 500_000_000);
418        assert_eq!(system.config().max_threads, 8);
419        assert_eq!(system.config().max_queue_size, 5_000);
420    }
421
422    #[test]
423    fn test_plugin_nerve_system_invalid_config() {
424        let config = SystemConfig {
425            max_memory_bytes: 0, // Invalid
426            max_threads: 8,
427            max_queue_size: 5_000,
428            performance_monitoring: true,
429            plugin_loading_strategy: PluginLoadingStrategy::LoadAll,
430        };
431
432        let system = PluginNerveSystem::with_config(config);
433        assert!(system.is_err());
434    }
435
436    #[test]
437    fn test_plugin_loading() {
438        let mut system = PluginNerveSystem::new().unwrap();
439
440        // Initially no plugins loaded
441        assert_eq!(system.plugin_count(), 0);
442
443        // Load plugins
444        let result = system.load_plugins();
445        assert!(result.is_ok());
446
447        // Should have all plugins loaded
448        assert_eq!(system.plugin_count(), 4);
449        assert!(system.is_healthy());
450    }
451
452    #[test]
453    fn test_system_statistics() {
454        let system = PluginNerveSystem::new().unwrap();
455        let stats = system.get_statistics();
456
457        // Initial statistics should be zero
458        assert_eq!(stats.messages_processed, 0);
459        assert_eq!(stats.errors_encountered, 0);
460    }
461
462    #[test]
463    fn test_health_status() {
464        let system = PluginNerveSystem::new().unwrap();
465        let status = system.health_status();
466
467        // Initial system should be healthy
468        assert_eq!(status, "Healthy");
469    }
470}