Michael Hu commited on
Commit
00156ab
·
1 Parent(s): 621a9bf
src/infrastructure/config/dependency_container.py CHANGED
@@ -67,12 +67,12 @@ class DependencyContainer:
67
  self._singletons: Dict[Type, Any] = {}
68
  self._scoped_instances: Dict[Type, Any] = {}
69
  self._lock = Lock()
70
-
71
  # Provider factories
72
  self._tts_factory: Optional[TTSProviderFactory] = None
73
  self._stt_factory: Optional[STTProviderFactory] = None
74
  self._translation_factory: Optional[TranslationProviderFactory] = None
75
-
76
  # Register default services
77
  self._register_default_services()
78
 
@@ -80,7 +80,7 @@ class DependencyContainer:
80
  """Register default service implementations."""
81
  # Register configuration as singleton
82
  self.register_singleton(AppConfig, self._config)
83
-
84
  # Register provider factories as singletons
85
  self.register_singleton(TTSProviderFactory, self._get_tts_factory)
86
  self.register_singleton(STTProviderFactory, self._get_stt_factory)
@@ -104,7 +104,7 @@ class DependencyContainer:
104
  # If implementation is already an instance, store it directly
105
  if not (isinstance(implementation, type) or callable(implementation)):
106
  self._singletons[service_type] = implementation
107
- logger.debug(f"Registered singleton instance for {service_type.__name__}")
108
  return
109
 
110
  descriptor = ServiceDescriptor(
@@ -114,7 +114,7 @@ class DependencyContainer:
114
  factory_args=factory_args
115
  )
116
  self._services[service_type] = descriptor
117
- logger.debug(f"Registered singleton service: {service_type.__name__}")
118
 
119
  def register_transient(
120
  self,
@@ -138,7 +138,7 @@ class DependencyContainer:
138
  factory_args=factory_args
139
  )
140
  self._services[service_type] = descriptor
141
- logger.debug(f"Registered transient service: {service_type.__name__}")
142
 
143
  def register_scoped(
144
  self,
@@ -162,7 +162,7 @@ class DependencyContainer:
162
  factory_args=factory_args
163
  )
164
  self._services[service_type] = descriptor
165
- logger.debug(f"Registered scoped service: {service_type.__name__}")
166
 
167
  def resolve(self, service_type: Type[T]) -> T:
168
  """
@@ -178,27 +178,43 @@ class DependencyContainer:
178
  ValueError: If service is not registered
179
  Exception: If service creation fails
180
  """
 
 
181
  with self._lock:
 
 
182
  # Check if already a singleton instance
183
  if service_type in self._singletons:
 
184
  return self._singletons[service_type]
185
 
186
  # Check if service is registered
187
  if service_type not in self._services:
 
188
  raise ValueError(f"Service {service_type.__name__} is not registered")
189
 
190
  descriptor = self._services[service_type]
 
191
 
192
  try:
193
  if descriptor.lifetime == ServiceLifetime.SINGLETON:
194
- return self._create_singleton(service_type, descriptor)
 
 
 
195
  elif descriptor.lifetime == ServiceLifetime.SCOPED:
196
- return self._create_scoped(service_type, descriptor)
 
 
 
197
  else: # TRANSIENT
198
- return self._create_transient(descriptor)
 
 
 
199
 
200
  except Exception as e:
201
- logger.error(f"Failed to resolve service {service_type.__name__}: {e}")
202
  raise
203
 
204
  def _create_singleton(self, service_type: Type[T], descriptor: ServiceDescriptor) -> T:
@@ -208,7 +224,7 @@ class DependencyContainer:
208
 
209
  instance = self._create_instance(descriptor)
210
  self._singletons[service_type] = instance
211
- logger.debug(f"Created singleton instance for {service_type.__name__}")
212
  return instance
213
 
214
  def _create_scoped(self, service_type: Type[T], descriptor: ServiceDescriptor) -> T:
@@ -218,49 +234,68 @@ class DependencyContainer:
218
 
219
  instance = self._create_instance(descriptor)
220
  self._scoped_instances[service_type] = instance
221
- logger.debug(f"Created scoped instance for {service_type.__name__}")
222
  return instance
223
 
224
  def _create_transient(self, descriptor: ServiceDescriptor) -> T:
225
  """Create new transient instance."""
226
  instance = self._create_instance(descriptor)
227
- logger.debug(f"Created transient instance for {descriptor.service_type.__name__}")
228
  return instance
229
 
230
  def _create_instance(self, descriptor: ServiceDescriptor) -> T:
231
  """Create service instance using descriptor."""
 
 
232
  implementation = descriptor.implementation
233
  factory_args = descriptor.factory_args
234
 
 
 
235
  # If implementation is a callable (factory function)
236
  if callable(implementation) and not isinstance(implementation, type):
237
- return implementation(**factory_args)
 
 
 
 
 
 
 
238
 
239
  # If implementation is a class
240
  if isinstance(implementation, type):
241
- return implementation(**factory_args)
 
 
 
 
 
 
 
242
 
 
243
  raise ValueError(f"Invalid implementation type for {descriptor.service_type.__name__}")
244
 
245
  def _get_tts_factory(self) -> TTSProviderFactory:
246
  """Get or create TTS provider factory."""
247
  if self._tts_factory is None:
248
  self._tts_factory = TTSProviderFactory()
249
- logger.debug("Created TTS provider factory")
250
  return self._tts_factory
251
 
252
  def _get_stt_factory(self) -> STTProviderFactory:
253
  """Get or create STT provider factory."""
254
  if self._stt_factory is None:
255
  self._stt_factory = STTProviderFactory()
256
- logger.debug("Created STT provider factory")
257
  return self._stt_factory
258
 
259
  def _get_translation_factory(self) -> TranslationProviderFactory:
260
  """Get or create translation provider factory."""
261
  if self._translation_factory is None:
262
  self._translation_factory = TranslationProviderFactory()
263
- logger.debug("Created translation provider factory")
264
  return self._translation_factory
265
 
266
  def get_tts_provider(self, provider_name: Optional[str] = None, **kwargs) -> ISpeechSynthesisService:
@@ -275,7 +310,7 @@ class DependencyContainer:
275
  ISpeechSynthesisService: TTS provider instance
276
  """
277
  factory = self.resolve(TTSProviderFactory)
278
-
279
  if provider_name:
280
  return factory.create_provider(provider_name, **kwargs)
281
  else:
@@ -293,7 +328,7 @@ class DependencyContainer:
293
  ISpeechRecognitionService: STT provider instance
294
  """
295
  factory = self.resolve(STTProviderFactory)
296
-
297
  if provider_name:
298
  return factory.create_provider(provider_name)
299
  else:
@@ -316,7 +351,7 @@ class DependencyContainer:
316
  ITranslationService: Translation provider instance
317
  """
318
  factory = self.resolve(TranslationProviderFactory)
319
-
320
  if provider_type:
321
  return factory.create_provider(provider_type, config)
322
  else:
@@ -328,9 +363,9 @@ class DependencyContainer:
328
  # Cleanup scoped instances if they have cleanup methods
329
  for instance in self._scoped_instances.values():
330
  self._cleanup_instance(instance)
331
-
332
  self._scoped_instances.clear()
333
- logger.debug("Cleared scoped instances")
334
 
335
  def _cleanup_instance(self, instance: Any) -> None:
336
  """Cleanup instance if it has cleanup methods."""
@@ -342,7 +377,7 @@ class DependencyContainer:
342
  method = getattr(instance, method_name)
343
  if callable(method):
344
  method()
345
- logger.debug(f"Called {method_name} on {type(instance).__name__}")
346
  break
347
  except Exception as e:
348
  logger.warning(f"Failed to cleanup instance {type(instance).__name__}: {e}")
@@ -351,33 +386,33 @@ class DependencyContainer:
351
  """Cleanup all managed resources."""
352
  with self._lock:
353
  logger.info("Starting dependency container cleanup")
354
-
355
  # Cleanup scoped instances
356
  self.clear_scoped_instances()
357
-
358
  # Cleanup singleton instances
359
  for instance in self._singletons.values():
360
  self._cleanup_instance(instance)
361
-
362
  # Cleanup provider factories
363
  if self._tts_factory:
364
  try:
365
  self._tts_factory.cleanup_providers()
366
  except Exception as e:
367
  logger.warning(f"Failed to cleanup TTS factory: {e}")
368
-
369
  if self._translation_factory:
370
  try:
371
  self._translation_factory.clear_cache()
372
  except Exception as e:
373
  logger.warning(f"Failed to cleanup translation factory: {e}")
374
-
375
  # Clear all references
376
  self._singletons.clear()
377
  self._tts_factory = None
378
  self._stt_factory = None
379
  self._translation_factory = None
380
-
381
  logger.info("Dependency container cleanup completed")
382
 
383
  def is_registered(self, service_type: Type) -> bool:
@@ -402,16 +437,16 @@ class DependencyContainer:
402
  """
403
  with self._lock:
404
  services_info = {}
405
-
406
  # Add singleton instances
407
  for service_type in self._singletons.keys():
408
  services_info[service_type.__name__] = "singleton (instance)"
409
-
410
  # Add registered services
411
  for service_type, descriptor in self._services.items():
412
  if service_type not in self._singletons:
413
  services_info[service_type.__name__] = descriptor.lifetime.value
414
-
415
  return services_info
416
 
417
  def create_scope(self) -> 'DependencyScope':
@@ -465,7 +500,7 @@ class DependencyScope:
465
  instance = self._parent.resolve(service_type)
466
 
467
  # If it's a scoped service, store it in this scope
468
- if (service_type in self._parent._services and
469
  self._parent._services[service_type].lifetime == ServiceLifetime.SCOPED):
470
  self._scoped_instances[service_type] = instance
471
 
@@ -500,12 +535,12 @@ def get_container() -> DependencyContainer:
500
  DependencyContainer: Global container instance
501
  """
502
  global _global_container
503
-
504
  with _container_lock:
505
  if _global_container is None:
506
  _global_container = DependencyContainer()
507
  logger.info("Created global dependency container")
508
-
509
  return _global_container
510
 
511
 
@@ -517,11 +552,11 @@ def set_container(container: DependencyContainer) -> None:
517
  container: Container instance to set as global
518
  """
519
  global _global_container
520
-
521
  with _container_lock:
522
  if _global_container is not None:
523
  _global_container.cleanup()
524
-
525
  _global_container = container
526
  logger.info("Set global dependency container")
527
 
@@ -529,7 +564,7 @@ def set_container(container: DependencyContainer) -> None:
529
  def cleanup_container() -> None:
530
  """Cleanup the global dependency container."""
531
  global _global_container
532
-
533
  with _container_lock:
534
  if _global_container is not None:
535
  _global_container.cleanup()
 
67
  self._singletons: Dict[Type, Any] = {}
68
  self._scoped_instances: Dict[Type, Any] = {}
69
  self._lock = Lock()
70
+
71
  # Provider factories
72
  self._tts_factory: Optional[TTSProviderFactory] = None
73
  self._stt_factory: Optional[STTProviderFactory] = None
74
  self._translation_factory: Optional[TranslationProviderFactory] = None
75
+
76
  # Register default services
77
  self._register_default_services()
78
 
 
80
  """Register default service implementations."""
81
  # Register configuration as singleton
82
  self.register_singleton(AppConfig, self._config)
83
+
84
  # Register provider factories as singletons
85
  self.register_singleton(TTSProviderFactory, self._get_tts_factory)
86
  self.register_singleton(STTProviderFactory, self._get_stt_factory)
 
104
  # If implementation is already an instance, store it directly
105
  if not (isinstance(implementation, type) or callable(implementation)):
106
  self._singletons[service_type] = implementation
107
+ logger.info(f"Registered singleton instance for {service_type.__name__}")
108
  return
109
 
110
  descriptor = ServiceDescriptor(
 
114
  factory_args=factory_args
115
  )
116
  self._services[service_type] = descriptor
117
+ logger.info(f"Registered singleton service: {service_type.__name__}")
118
 
119
  def register_transient(
120
  self,
 
138
  factory_args=factory_args
139
  )
140
  self._services[service_type] = descriptor
141
+ logger.info(f"Registered transient service: {service_type.__name__}")
142
 
143
  def register_scoped(
144
  self,
 
162
  factory_args=factory_args
163
  )
164
  self._services[service_type] = descriptor
165
+ logger.info(f"Registered scoped service: {service_type.__name__}")
166
 
167
  def resolve(self, service_type: Type[T]) -> T:
168
  """
 
178
  ValueError: If service is not registered
179
  Exception: If service creation fails
180
  """
181
+ logger.info(f"Starting resolve for service: {service_type.__name__}")
182
+
183
  with self._lock:
184
+ logger.info(f"Acquired lock for resolving: {service_type.__name__}")
185
+
186
  # Check if already a singleton instance
187
  if service_type in self._singletons:
188
+ logger.info(f"Found existing singleton instance for: {service_type.__name__}")
189
  return self._singletons[service_type]
190
 
191
  # Check if service is registered
192
  if service_type not in self._services:
193
+ logger.error(f"Service {service_type.__name__} is not registered")
194
  raise ValueError(f"Service {service_type.__name__} is not registered")
195
 
196
  descriptor = self._services[service_type]
197
+ logger.info(f"Found service descriptor for {service_type.__name__} with lifetime: {descriptor.lifetime.value}")
198
 
199
  try:
200
  if descriptor.lifetime == ServiceLifetime.SINGLETON:
201
+ logger.info(f"Creating singleton for: {service_type.__name__}")
202
+ result = self._create_singleton(service_type, descriptor)
203
+ logger.info(f"Successfully created singleton for: {service_type.__name__}")
204
+ return result
205
  elif descriptor.lifetime == ServiceLifetime.SCOPED:
206
+ logger.info(f"Creating scoped instance for: {service_type.__name__}")
207
+ result = self._create_scoped(service_type, descriptor)
208
+ logger.info(f"Successfully created scoped instance for: {service_type.__name__}")
209
+ return result
210
  else: # TRANSIENT
211
+ logger.info(f"Creating transient instance for: {service_type.__name__}")
212
+ result = self._create_transient(descriptor)
213
+ logger.info(f"Successfully created transient instance for: {service_type.__name__}")
214
+ return result
215
 
216
  except Exception as e:
217
+ logger.error(f"Failed to resolve service {service_type.__name__}: {e}", exc_info=True)
218
  raise
219
 
220
  def _create_singleton(self, service_type: Type[T], descriptor: ServiceDescriptor) -> T:
 
224
 
225
  instance = self._create_instance(descriptor)
226
  self._singletons[service_type] = instance
227
+ logger.info(f"Created singleton instance for {service_type.__name__}")
228
  return instance
229
 
230
  def _create_scoped(self, service_type: Type[T], descriptor: ServiceDescriptor) -> T:
 
234
 
235
  instance = self._create_instance(descriptor)
236
  self._scoped_instances[service_type] = instance
237
+ logger.info(f"Created scoped instance for {service_type.__name__}")
238
  return instance
239
 
240
  def _create_transient(self, descriptor: ServiceDescriptor) -> T:
241
  """Create new transient instance."""
242
  instance = self._create_instance(descriptor)
243
+ logger.info(f"Created transient instance for {descriptor.service_type.__name__}")
244
  return instance
245
 
246
  def _create_instance(self, descriptor: ServiceDescriptor) -> T:
247
  """Create service instance using descriptor."""
248
+ logger.info(f"Creating instance for {descriptor.service_type.__name__}")
249
+
250
  implementation = descriptor.implementation
251
  factory_args = descriptor.factory_args
252
 
253
+ logger.info(f"Implementation type: {type(implementation)}, Factory args: {factory_args}")
254
+
255
  # If implementation is a callable (factory function)
256
  if callable(implementation) and not isinstance(implementation, type):
257
+ logger.info(f"Calling factory function for {descriptor.service_type.__name__}")
258
+ try:
259
+ result = implementation(**factory_args)
260
+ logger.info(f"Factory function completed for {descriptor.service_type.__name__}")
261
+ return result
262
+ except Exception as e:
263
+ logger.error(f"Factory function failed for {descriptor.service_type.__name__}: {e}", exc_info=True)
264
+ raise
265
 
266
  # If implementation is a class
267
  if isinstance(implementation, type):
268
+ logger.info(f"Instantiating class {implementation.__name__} for {descriptor.service_type.__name__}")
269
+ try:
270
+ result = implementation(**factory_args)
271
+ logger.info(f"Class instantiation completed for {descriptor.service_type.__name__}")
272
+ return result
273
+ except Exception as e:
274
+ logger.error(f"Class instantiation failed for {descriptor.service_type.__name__}: {e}", exc_info=True)
275
+ raise
276
 
277
+ logger.error(f"Invalid implementation type for {descriptor.service_type.__name__}: {type(implementation)}")
278
  raise ValueError(f"Invalid implementation type for {descriptor.service_type.__name__}")
279
 
280
  def _get_tts_factory(self) -> TTSProviderFactory:
281
  """Get or create TTS provider factory."""
282
  if self._tts_factory is None:
283
  self._tts_factory = TTSProviderFactory()
284
+ logger.info("Created TTS provider factory")
285
  return self._tts_factory
286
 
287
  def _get_stt_factory(self) -> STTProviderFactory:
288
  """Get or create STT provider factory."""
289
  if self._stt_factory is None:
290
  self._stt_factory = STTProviderFactory()
291
+ logger.info("Created STT provider factory")
292
  return self._stt_factory
293
 
294
  def _get_translation_factory(self) -> TranslationProviderFactory:
295
  """Get or create translation provider factory."""
296
  if self._translation_factory is None:
297
  self._translation_factory = TranslationProviderFactory()
298
+ logger.info("Created translation provider factory")
299
  return self._translation_factory
300
 
301
  def get_tts_provider(self, provider_name: Optional[str] = None, **kwargs) -> ISpeechSynthesisService:
 
310
  ISpeechSynthesisService: TTS provider instance
311
  """
312
  factory = self.resolve(TTSProviderFactory)
313
+
314
  if provider_name:
315
  return factory.create_provider(provider_name, **kwargs)
316
  else:
 
328
  ISpeechRecognitionService: STT provider instance
329
  """
330
  factory = self.resolve(STTProviderFactory)
331
+
332
  if provider_name:
333
  return factory.create_provider(provider_name)
334
  else:
 
351
  ITranslationService: Translation provider instance
352
  """
353
  factory = self.resolve(TranslationProviderFactory)
354
+
355
  if provider_type:
356
  return factory.create_provider(provider_type, config)
357
  else:
 
363
  # Cleanup scoped instances if they have cleanup methods
364
  for instance in self._scoped_instances.values():
365
  self._cleanup_instance(instance)
366
+
367
  self._scoped_instances.clear()
368
+ logger.info("Cleared scoped instances")
369
 
370
  def _cleanup_instance(self, instance: Any) -> None:
371
  """Cleanup instance if it has cleanup methods."""
 
377
  method = getattr(instance, method_name)
378
  if callable(method):
379
  method()
380
+ logger.info(f"Called {method_name} on {type(instance).__name__}")
381
  break
382
  except Exception as e:
383
  logger.warning(f"Failed to cleanup instance {type(instance).__name__}: {e}")
 
386
  """Cleanup all managed resources."""
387
  with self._lock:
388
  logger.info("Starting dependency container cleanup")
389
+
390
  # Cleanup scoped instances
391
  self.clear_scoped_instances()
392
+
393
  # Cleanup singleton instances
394
  for instance in self._singletons.values():
395
  self._cleanup_instance(instance)
396
+
397
  # Cleanup provider factories
398
  if self._tts_factory:
399
  try:
400
  self._tts_factory.cleanup_providers()
401
  except Exception as e:
402
  logger.warning(f"Failed to cleanup TTS factory: {e}")
403
+
404
  if self._translation_factory:
405
  try:
406
  self._translation_factory.clear_cache()
407
  except Exception as e:
408
  logger.warning(f"Failed to cleanup translation factory: {e}")
409
+
410
  # Clear all references
411
  self._singletons.clear()
412
  self._tts_factory = None
413
  self._stt_factory = None
414
  self._translation_factory = None
415
+
416
  logger.info("Dependency container cleanup completed")
417
 
418
  def is_registered(self, service_type: Type) -> bool:
 
437
  """
438
  with self._lock:
439
  services_info = {}
440
+
441
  # Add singleton instances
442
  for service_type in self._singletons.keys():
443
  services_info[service_type.__name__] = "singleton (instance)"
444
+
445
  # Add registered services
446
  for service_type, descriptor in self._services.items():
447
  if service_type not in self._singletons:
448
  services_info[service_type.__name__] = descriptor.lifetime.value
449
+
450
  return services_info
451
 
452
  def create_scope(self) -> 'DependencyScope':
 
500
  instance = self._parent.resolve(service_type)
501
 
502
  # If it's a scoped service, store it in this scope
503
+ if (service_type in self._parent._services and
504
  self._parent._services[service_type].lifetime == ServiceLifetime.SCOPED):
505
  self._scoped_instances[service_type] = instance
506
 
 
535
  DependencyContainer: Global container instance
536
  """
537
  global _global_container
538
+
539
  with _container_lock:
540
  if _global_container is None:
541
  _global_container = DependencyContainer()
542
  logger.info("Created global dependency container")
543
+
544
  return _global_container
545
 
546
 
 
552
  container: Container instance to set as global
553
  """
554
  global _global_container
555
+
556
  with _container_lock:
557
  if _global_container is not None:
558
  _global_container.cleanup()
559
+
560
  _global_container = container
561
  logger.info("Set global dependency container")
562
 
 
564
  def cleanup_container() -> None:
565
  """Cleanup the global dependency container."""
566
  global _global_container
567
+
568
  with _container_lock:
569
  if _global_container is not None:
570
  _global_container.cleanup()