elif_core/container/
registry.rs1use 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
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>(&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 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 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 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 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 pub fn service_count(&self) -> usize {
156 self.services.read()
157 .map(|services| services.len())
158 .unwrap_or(0)
159 }
160
161 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 pub fn validate(&self) -> Result<(), CoreError> {
170 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 pub async fn initialize_all(&self) -> Result<(), CoreError> {
184 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 registry.register_singleton(service).unwrap();
238
239 let instance1 = registry.resolve::<TestService>().unwrap();
241 let instance2 = registry.resolve::<TestService>().unwrap();
242 let instance3 = registry.resolve::<TestService>().unwrap();
243
244 assert_eq!(instance1.id, original_id);
246 assert_eq!(instance2.id, original_id);
247 assert_eq!(instance3.id, original_id);
248
249 let count1 = instance1.increment();
251 assert_eq!(count1, 1);
252
253 assert_eq!(instance2.get_count(), 1);
255 assert_eq!(instance3.get_count(), 1);
256
257 let count2 = instance2.increment();
259 assert_eq!(count2, 2);
260
261 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 let instance1 = registry.resolve::<TestService>().unwrap();
275 let instance2 = registry.resolve::<TestService>().unwrap();
276
277 assert!(Arc::ptr_eq(&instance1, &instance2));
279 }
280
281 #[test]
282 fn test_transient_behavior() {
283 let mut registry = ServiceRegistry::new();
284
285 registry.register_transient::<TestService>(Box::new(|| TestService::new())).unwrap();
287
288 let instance1 = registry.resolve::<TestService>().unwrap();
290 let instance2 = registry.resolve::<TestService>().unwrap();
291
292 assert_ne!(instance1.id, instance2.id);
294
295 assert!(!Arc::ptr_eq(&instance1, &instance2));
297
298 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 assert!(!registry.contains::<TestService>());
311 assert_eq!(registry.service_count(), 0);
312
313 registry.register_singleton(service).unwrap();
315
316 assert!(registry.contains::<TestService>());
318 assert_eq!(registry.service_count(), 1);
319
320 let resolved = registry.resolve::<TestService>().unwrap();
322 assert_eq!(resolved.service_id(), "elif_core::container::registry::tests::TestService");
323 }
324}