elif_core/container/
registry.rs

1use crate::foundation::traits::Service;
2use crate::container::scope::ServiceScope;
3use crate::errors::CoreError;
4use std::any::{Any, TypeId};
5use std::collections::HashMap;
6use std::sync::{Arc, RwLock};
7
8/// Service entry in the registry
9pub enum ServiceEntry {
10    /// Single instance (singleton)
11    Instance(Arc<dyn Any + Send + Sync>),
12    /// Factory function for creating instances
13    Factory(Box<dyn Fn() -> Box<dyn Any + Send + Sync> + Send + Sync>),
14}
15
16impl std::fmt::Debug for ServiceEntry {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        match self {
19            ServiceEntry::Instance(_) => f.debug_tuple("Instance").field(&"<instance>").finish(),
20            ServiceEntry::Factory(_) => f.debug_tuple("Factory").field(&"<factory>").finish(),
21        }
22    }
23}
24
25/// Registry for managing service instances and factories
26#[derive(Debug)]
27pub struct ServiceRegistry {
28    services: Arc<RwLock<HashMap<TypeId, ServiceEntry>>>,
29    scopes: Arc<RwLock<HashMap<TypeId, ServiceScope>>>,
30}
31
32impl ServiceRegistry {
33    /// Create a new service registry
34    pub fn new() -> Self {
35        Self {
36            services: Arc::new(RwLock::new(HashMap::new())),
37            scopes: Arc::new(RwLock::new(HashMap::new())),
38        }
39    }
40    
41    /// Register a service instance
42    pub fn register_service<T>(&mut self, service: T) -> Result<(), CoreError>
43    where
44        T: Service + Clone + 'static,
45    {
46        let type_id = TypeId::of::<T>();
47        let arc_service = Arc::new(service);
48        
49        let mut services = self.services.write().map_err(|_| CoreError::LockError {
50            resource: "service_registry".to_string(),
51        })?;
52        
53        let mut scopes = self.scopes.write().map_err(|_| CoreError::LockError {
54            resource: "service_scopes".to_string(),
55        })?;
56        
57        services.insert(type_id, ServiceEntry::Instance(arc_service));
58        scopes.insert(type_id, ServiceScope::Singleton);
59        
60        Ok(())
61    }
62    
63    /// Register a singleton service
64    pub fn register_singleton<T>(&mut self, service: T) -> Result<(), CoreError>
65    where
66        T: Service + Clone + 'static,
67    {
68        let type_id = TypeId::of::<T>();
69        let arc_service = Arc::new(service);
70        
71        let mut services = self.services.write().map_err(|_| CoreError::LockError {
72            resource: "service_registry".to_string(),
73        })?;
74        
75        let mut scopes = self.scopes.write().map_err(|_| CoreError::LockError {
76            resource: "service_scopes".to_string(),
77        })?;
78        
79        services.insert(type_id, ServiceEntry::Instance(arc_service));
80        scopes.insert(type_id, ServiceScope::Singleton);
81        
82        Ok(())
83    }
84    
85    /// Register a transient service factory
86    pub fn register_transient<T>(&mut self, factory: Box<dyn Fn() -> T + Send + Sync>) -> Result<(), CoreError>
87    where
88        T: Service + 'static,
89    {
90        let type_id = TypeId::of::<T>();
91        
92        let wrapped_factory: Box<dyn Fn() -> Box<dyn Any + Send + Sync> + Send + Sync> = 
93            Box::new(move || -> Box<dyn Any + Send + Sync> {
94                Box::new(factory())
95            });
96        
97        let mut services = self.services.write().map_err(|_| CoreError::LockError {
98            resource: "service_registry".to_string(),
99        })?;
100        
101        let mut scopes = self.scopes.write().map_err(|_| CoreError::LockError {
102            resource: "service_scopes".to_string(),
103        })?;
104        
105        services.insert(type_id, ServiceEntry::Factory(wrapped_factory));
106        scopes.insert(type_id, ServiceScope::Transient);
107        
108        Ok(())
109    }
110    
111    /// Resolve a service instance
112    pub fn resolve<T>(&self) -> Result<Arc<T>, CoreError>
113    where
114        T: Service + Clone + 'static,
115    {
116        self.try_resolve::<T>()
117            .ok_or_else(|| CoreError::ServiceNotFound {
118                service_type: std::any::type_name::<T>().to_string(),
119            })
120    }
121    
122    /// Try to resolve a service instance
123    pub fn try_resolve<T>(&self) -> Option<Arc<T>>
124    where
125        T: Service + Clone + 'static,
126    {
127        let type_id = TypeId::of::<T>();
128        let services = self.services.read().ok()?;
129        
130        match services.get(&type_id)? {
131            ServiceEntry::Instance(instance) => {
132                // Clone the Arc itself, not the service - this maintains singleton behavior
133                instance.clone().downcast::<T>().ok()
134            }
135            ServiceEntry::Factory(factory) => {
136                let instance = factory();
137                let boxed = instance.downcast::<T>().ok()?;
138                Some(Arc::new(*boxed))
139            }
140        }
141    }
142    
143    /// Check if a service type is registered
144    pub fn contains<T>(&self) -> bool
145    where
146        T: Service + 'static,
147    {
148        let type_id = TypeId::of::<T>();
149        self.services.read()
150            .map(|services| services.contains_key(&type_id))
151            .unwrap_or(false)
152    }
153    
154    /// Get the number of registered services
155    pub fn service_count(&self) -> usize {
156        self.services.read()
157            .map(|services| services.len())
158            .unwrap_or(0)
159    }
160    
161    /// Get all registered service type IDs
162    pub fn registered_services(&self) -> Vec<TypeId> {
163        self.services.read()
164            .map(|services| services.keys().cloned().collect())
165            .unwrap_or_default()
166    }
167    
168    /// Validate all registered services
169    pub fn validate(&self) -> Result<(), CoreError> {
170        // For now, just check that we can acquire read locks
171        let _services = self.services.read().map_err(|_| CoreError::LockError {
172            resource: "service_registry".to_string(),
173        })?;
174        
175        let _scopes = self.scopes.read().map_err(|_| CoreError::LockError {
176            resource: "service_scopes".to_string(),
177        })?;
178        
179        Ok(())
180    }
181    
182    /// Initialize all services that implement Initializable
183    pub async fn initialize_all(&self) -> Result<(), CoreError> {
184        // This is a simplified version - in a real implementation,
185        // we would need to handle service dependencies and initialization order
186        self.validate()
187    }
188}
189
190impl Default for ServiceRegistry {
191    fn default() -> Self {
192        Self::new()
193    }
194}
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199    use crate::foundation::traits::Service;
200    use std::sync::atomic::{AtomicUsize, Ordering};
201    
202    #[derive(Debug, Clone)]
203    struct TestService {
204        id: usize,
205        counter: Arc<AtomicUsize>,
206    }
207    
208    impl TestService {
209        fn new() -> Self {
210            static COUNTER: AtomicUsize = AtomicUsize::new(0);
211            Self {
212                id: COUNTER.fetch_add(1, Ordering::SeqCst),
213                counter: Arc::new(AtomicUsize::new(0)),
214            }
215        }
216        
217        fn increment(&self) -> usize {
218            self.counter.fetch_add(1, Ordering::SeqCst) + 1
219        }
220        
221        fn get_count(&self) -> usize {
222            self.counter.load(Ordering::SeqCst)
223        }
224    }
225    
226    impl crate::foundation::traits::FrameworkComponent for TestService {}
227    
228    impl Service for TestService {}
229    
230    #[test]
231    fn test_singleton_behavior() {
232        let mut registry = ServiceRegistry::new();
233        let service = TestService::new();
234        let original_id = service.id;
235        
236        // Register as singleton
237        registry.register_singleton(service).unwrap();
238        
239        // Resolve multiple times
240        let instance1 = registry.resolve::<TestService>().unwrap();
241        let instance2 = registry.resolve::<TestService>().unwrap();
242        let instance3 = registry.resolve::<TestService>().unwrap();
243        
244        // All instances should have the same ID (same original service)
245        assert_eq!(instance1.id, original_id);
246        assert_eq!(instance2.id, original_id);
247        assert_eq!(instance3.id, original_id);
248        
249        // Increment counter on one instance
250        let count1 = instance1.increment();
251        assert_eq!(count1, 1);
252        
253        // Other instances should see the same count (shared state)
254        assert_eq!(instance2.get_count(), 1);
255        assert_eq!(instance3.get_count(), 1);
256        
257        // Increment on another instance
258        let count2 = instance2.increment();
259        assert_eq!(count2, 2);
260        
261        // All should see the updated count
262        assert_eq!(instance1.get_count(), 2);
263        assert_eq!(instance3.get_count(), 2);
264    }
265    
266    #[test]
267    fn test_singleton_arc_sharing() {
268        let mut registry = ServiceRegistry::new();
269        let service = TestService::new();
270        
271        registry.register_singleton(service).unwrap();
272        
273        // Resolve multiple times
274        let instance1 = registry.resolve::<TestService>().unwrap();
275        let instance2 = registry.resolve::<TestService>().unwrap();
276        
277        // The Arc pointers should be the same (true singleton)
278        assert!(Arc::ptr_eq(&instance1, &instance2));
279    }
280    
281    #[test]
282    fn test_transient_behavior() {
283        let mut registry = ServiceRegistry::new();
284        
285        // Register transient factory
286        registry.register_transient::<TestService>(Box::new(|| TestService::new())).unwrap();
287        
288        // Resolve multiple times
289        let instance1 = registry.resolve::<TestService>().unwrap();
290        let instance2 = registry.resolve::<TestService>().unwrap();
291        
292        // Each instance should have different IDs (new instances)
293        assert_ne!(instance1.id, instance2.id);
294        
295        // The Arc pointers should be different (different instances)
296        assert!(!Arc::ptr_eq(&instance1, &instance2));
297        
298        // Increment on one should not affect the other
299        instance1.increment();
300        assert_eq!(instance1.get_count(), 1);
301        assert_eq!(instance2.get_count(), 0);
302    }
303    
304    #[test]
305    fn test_service_registry_operations() {
306        let mut registry = ServiceRegistry::new();
307        let service = TestService::new();
308        
309        // Initially empty
310        assert!(!registry.contains::<TestService>());
311        assert_eq!(registry.service_count(), 0);
312        
313        // Register service
314        registry.register_singleton(service).unwrap();
315        
316        // Should now contain the service
317        assert!(registry.contains::<TestService>());
318        assert_eq!(registry.service_count(), 1);
319        
320        // Should be able to resolve
321        let resolved = registry.resolve::<TestService>().unwrap();
322        assert_eq!(resolved.service_id(), "elif_core::container::registry::tests::TestService");
323    }
324}