elif_core/container/
registry.rs1use crate::container::scope::ServiceScope;
2use crate::errors::CoreError;
3use crate::foundation::traits::Service;
4use std::any::{Any, TypeId};
5use std::collections::HashMap;
6use std::sync::{Arc, RwLock};
7
8pub enum ServiceEntry {
10 Instance(Arc<dyn Any + Send + Sync>),
12 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#[derive(Debug)]
27pub struct ServiceRegistry {
28 services: Arc<RwLock<HashMap<TypeId, ServiceEntry>>>,
29 scopes: Arc<RwLock<HashMap<TypeId, ServiceScope>>>,
30}
31
32impl ServiceRegistry {
33 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 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 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 pub fn register_transient<T>(
87 &mut self,
88 factory: Box<dyn Fn() -> T + Send + Sync>,
89 ) -> Result<(), CoreError>
90 where
91 T: Service + 'static,
92 {
93 let type_id = TypeId::of::<T>();
94
95 let wrapped_factory: Box<dyn Fn() -> Box<dyn Any + Send + Sync> + Send + Sync> =
96 Box::new(move || -> Box<dyn Any + Send + Sync> { Box::new(factory()) });
97
98 let mut services = self.services.write().map_err(|_| CoreError::LockError {
99 resource: "service_registry".to_string(),
100 })?;
101
102 let mut scopes = self.scopes.write().map_err(|_| CoreError::LockError {
103 resource: "service_scopes".to_string(),
104 })?;
105
106 services.insert(type_id, ServiceEntry::Factory(wrapped_factory));
107 scopes.insert(type_id, ServiceScope::Transient);
108
109 Ok(())
110 }
111
112 pub fn resolve<T>(&self) -> Result<Arc<T>, CoreError>
114 where
115 T: Service + Clone + 'static,
116 {
117 self.try_resolve::<T>()
118 .ok_or_else(|| CoreError::ServiceNotFound {
119 service_type: std::any::type_name::<T>().to_string(),
120 })
121 }
122
123 pub fn try_resolve<T>(&self) -> Option<Arc<T>>
125 where
126 T: Service + Clone + 'static,
127 {
128 let type_id = TypeId::of::<T>();
129 let services = self.services.read().ok()?;
130
131 match services.get(&type_id)? {
132 ServiceEntry::Instance(instance) => {
133 instance.clone().downcast::<T>().ok()
135 }
136 ServiceEntry::Factory(factory) => {
137 let instance = factory();
138 let boxed = instance.downcast::<T>().ok()?;
139 Some(Arc::new(*boxed))
140 }
141 }
142 }
143
144 pub fn contains<T>(&self) -> bool
146 where
147 T: Service + 'static,
148 {
149 let type_id = TypeId::of::<T>();
150 self.services
151 .read()
152 .map(|services| services.contains_key(&type_id))
153 .unwrap_or(false)
154 }
155
156 pub fn service_count(&self) -> usize {
158 self.services
159 .read()
160 .map(|services| services.len())
161 .unwrap_or(0)
162 }
163
164 pub fn registered_services(&self) -> Vec<TypeId> {
166 self.services
167 .read()
168 .map(|services| services.keys().cloned().collect())
169 .unwrap_or_default()
170 }
171
172 pub fn validate(&self) -> Result<(), CoreError> {
174 let _services = self.services.read().map_err(|_| CoreError::LockError {
176 resource: "service_registry".to_string(),
177 })?;
178
179 let _scopes = self.scopes.read().map_err(|_| CoreError::LockError {
180 resource: "service_scopes".to_string(),
181 })?;
182
183 Ok(())
184 }
185
186 pub async fn initialize_all(&self) -> Result<(), CoreError> {
188 self.validate()
191 }
192}
193
194impl Default for ServiceRegistry {
195 fn default() -> Self {
196 Self::new()
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203 use crate::foundation::traits::Service;
204 use std::sync::atomic::{AtomicUsize, Ordering};
205
206 #[derive(Debug, Clone)]
207 struct TestService {
208 id: usize,
209 counter: Arc<AtomicUsize>,
210 }
211
212 impl TestService {
213 fn new() -> Self {
214 static COUNTER: AtomicUsize = AtomicUsize::new(0);
215 Self {
216 id: COUNTER.fetch_add(1, Ordering::SeqCst),
217 counter: Arc::new(AtomicUsize::new(0)),
218 }
219 }
220
221 fn increment(&self) -> usize {
222 self.counter.fetch_add(1, Ordering::SeqCst) + 1
223 }
224
225 fn get_count(&self) -> usize {
226 self.counter.load(Ordering::SeqCst)
227 }
228 }
229
230 impl crate::foundation::traits::FrameworkComponent for TestService {}
231
232 impl Service for TestService {}
233
234 #[test]
235 fn test_singleton_behavior() {
236 let mut registry = ServiceRegistry::new();
237 let service = TestService::new();
238 let original_id = service.id;
239
240 registry.register_singleton(service).unwrap();
242
243 let instance1 = registry.resolve::<TestService>().unwrap();
245 let instance2 = registry.resolve::<TestService>().unwrap();
246 let instance3 = registry.resolve::<TestService>().unwrap();
247
248 assert_eq!(instance1.id, original_id);
250 assert_eq!(instance2.id, original_id);
251 assert_eq!(instance3.id, original_id);
252
253 let count1 = instance1.increment();
255 assert_eq!(count1, 1);
256
257 assert_eq!(instance2.get_count(), 1);
259 assert_eq!(instance3.get_count(), 1);
260
261 let count2 = instance2.increment();
263 assert_eq!(count2, 2);
264
265 assert_eq!(instance1.get_count(), 2);
267 assert_eq!(instance3.get_count(), 2);
268 }
269
270 #[test]
271 fn test_singleton_arc_sharing() {
272 let mut registry = ServiceRegistry::new();
273 let service = TestService::new();
274
275 registry.register_singleton(service).unwrap();
276
277 let instance1 = registry.resolve::<TestService>().unwrap();
279 let instance2 = registry.resolve::<TestService>().unwrap();
280
281 assert!(Arc::ptr_eq(&instance1, &instance2));
283 }
284
285 #[test]
286 fn test_transient_behavior() {
287 let mut registry = ServiceRegistry::new();
288
289 registry
291 .register_transient::<TestService>(Box::new(|| TestService::new()))
292 .unwrap();
293
294 let instance1 = registry.resolve::<TestService>().unwrap();
296 let instance2 = registry.resolve::<TestService>().unwrap();
297
298 assert_ne!(instance1.id, instance2.id);
300
301 assert!(!Arc::ptr_eq(&instance1, &instance2));
303
304 instance1.increment();
306 assert_eq!(instance1.get_count(), 1);
307 assert_eq!(instance2.get_count(), 0);
308 }
309
310 #[test]
311 fn test_service_registry_operations() {
312 let mut registry = ServiceRegistry::new();
313 let service = TestService::new();
314
315 assert!(!registry.contains::<TestService>());
317 assert_eq!(registry.service_count(), 0);
318
319 registry.register_singleton(service).unwrap();
321
322 assert!(registry.contains::<TestService>());
324 assert_eq!(registry.service_count(), 1);
325
326 let resolved = registry.resolve::<TestService>().unwrap();
328 assert_eq!(
329 resolved.service_id(),
330 "elif_core::container::registry::tests::TestService"
331 );
332 }
333}