Spaces:
Sleeping
Sleeping
| """Container setup module for registering all services and dependencies.""" | |
| import logging | |
| from typing import Optional | |
| from .app_config import AppConfig | |
| from .dependency_container import DependencyContainer, ServiceLifetime | |
| from ..tts.provider_factory import TTSProviderFactory | |
| from ..stt.provider_factory import STTProviderFactory | |
| from ..translation.provider_factory import TranslationProviderFactory | |
| from ...domain.interfaces.audio_processing import IAudioProcessingService | |
| from ...domain.interfaces.speech_recognition import ISpeechRecognitionService | |
| from ...domain.interfaces.translation import ITranslationService | |
| from ...domain.interfaces.speech_synthesis import ISpeechSynthesisService | |
| from ...domain.services.audio_processing_service import AudioProcessingService | |
| from ...application.services.audio_processing_service import AudioProcessingApplicationService | |
| from ...application.services.configuration_service import ConfigurationApplicationService | |
| logger = logging.getLogger(__name__) | |
| def setup_container(config_file: Optional[str] = None) -> DependencyContainer: | |
| """ | |
| Set up and configure the dependency injection container with all services. | |
| Args: | |
| config_file: Optional path to configuration file | |
| Returns: | |
| DependencyContainer: Configured container instance | |
| """ | |
| logger.info("Setting up dependency injection container") | |
| # Create configuration | |
| config = AppConfig(config_file=config_file) | |
| # Create container with configuration | |
| container = DependencyContainer(config) | |
| # Register core services | |
| _register_core_services(container, config) | |
| # Register domain services | |
| _register_domain_services(container) | |
| # Register application services | |
| _register_application_services(container) | |
| # Register provider services | |
| _register_provider_services(container) | |
| logger.info("Dependency injection container setup completed") | |
| return container | |
| def _register_core_services(container: DependencyContainer, config: AppConfig) -> None: | |
| """ | |
| Register core infrastructure services. | |
| Args: | |
| container: Dependency container | |
| config: Application configuration | |
| """ | |
| logger.info("Registering core services") | |
| # Configuration is already registered as singleton in container constructor | |
| # But we ensure it's the same instance | |
| container.register_singleton(AppConfig, config) | |
| # Register provider factories as singletons | |
| container.register_singleton( | |
| TTSProviderFactory, | |
| lambda: TTSProviderFactory() | |
| ) | |
| container.register_singleton( | |
| STTProviderFactory, | |
| lambda: STTProviderFactory() | |
| ) | |
| container.register_singleton( | |
| TranslationProviderFactory, | |
| lambda: TranslationProviderFactory() | |
| ) | |
| logger.info("Core services registered") | |
| def _register_domain_services(container: DependencyContainer) -> None: | |
| """ | |
| Register domain services. | |
| Args: | |
| container: Dependency container | |
| """ | |
| logger.info("Registering domain services") | |
| # Register domain audio processing service as transient | |
| # It requires other services to be injected | |
| def create_audio_processing_service() -> IAudioProcessingService: | |
| """Factory function for creating audio processing service.""" | |
| # Get provider services from container | |
| stt_provider = container.get_stt_provider() | |
| translation_provider = container.get_translation_provider() | |
| tts_provider = container.get_tts_provider() | |
| return AudioProcessingService( | |
| speech_recognition_service=stt_provider, | |
| translation_service=translation_provider, | |
| speech_synthesis_service=tts_provider | |
| ) | |
| container.register_transient( | |
| IAudioProcessingService, | |
| create_audio_processing_service | |
| ) | |
| logger.info("Domain services registered") | |
| def _register_application_services(container: DependencyContainer) -> None: | |
| """ | |
| Register application services. | |
| Args: | |
| container: Dependency container | |
| """ | |
| logger.info("Registering application services") | |
| # Register audio processing application service as scoped | |
| # It manages resources and should be scoped to request/session | |
| def create_audio_processing_app_service() -> AudioProcessingApplicationService: | |
| """Factory function for creating audio processing application service.""" | |
| return AudioProcessingApplicationService(container) | |
| container.register_scoped( | |
| AudioProcessingApplicationService, | |
| create_audio_processing_app_service | |
| ) | |
| # Register configuration application service as singleton | |
| # Configuration service can be shared across requests | |
| def create_configuration_app_service() -> ConfigurationApplicationService: | |
| """Factory function for creating configuration application service.""" | |
| return ConfigurationApplicationService(container) | |
| container.register_singleton( | |
| ConfigurationApplicationService, | |
| create_configuration_app_service | |
| ) | |
| logger.info("Application services registered") | |
| def _register_provider_services(container: DependencyContainer) -> None: | |
| """ | |
| Register provider services with fallback logic. | |
| Args: | |
| container: Dependency container | |
| """ | |
| logger.info("Registering provider services") | |
| # Register TTS provider service as transient with fallback | |
| def create_tts_provider() -> ISpeechSynthesisService: | |
| """Factory function for creating TTS provider with fallback.""" | |
| return container.get_tts_provider() | |
| container.register_transient( | |
| ISpeechSynthesisService, | |
| create_tts_provider | |
| ) | |
| # Register STT provider service as transient with fallback | |
| def create_stt_provider() -> ISpeechRecognitionService: | |
| """Factory function for creating STT provider with fallback.""" | |
| return container.get_stt_provider() | |
| container.register_transient( | |
| ISpeechRecognitionService, | |
| create_stt_provider | |
| ) | |
| # Register translation provider service as transient with fallback | |
| def create_translation_provider() -> ITranslationService: | |
| """Factory function for creating translation provider with fallback.""" | |
| return container.get_translation_provider() | |
| container.register_transient( | |
| ITranslationService, | |
| create_translation_provider | |
| ) | |
| logger.info("Provider services registered") | |
| def configure_logging(config: AppConfig) -> None: | |
| """ | |
| Configure application logging based on configuration. | |
| Args: | |
| config: Application configuration | |
| """ | |
| try: | |
| logging_config = config.get_logging_config() | |
| # Configure root logger | |
| root_logger = logging.getLogger() | |
| root_logger.setLevel(getattr(logging, logging_config['level'].upper(), logging.INFO)) | |
| # Clear existing handlers | |
| for handler in root_logger.handlers[:]: | |
| root_logger.removeHandler(handler) | |
| # Create console handler | |
| console_handler = logging.StreamHandler() | |
| console_handler.setLevel(root_logger.level) | |
| # Create formatter | |
| formatter = logging.Formatter(logging_config['format']) | |
| console_handler.setFormatter(formatter) | |
| # Add console handler | |
| root_logger.addHandler(console_handler) | |
| # Add file handler if enabled | |
| if logging_config.get('enable_file_logging', False): | |
| from logging.handlers import RotatingFileHandler | |
| file_handler = RotatingFileHandler( | |
| logging_config['log_file_path'], | |
| maxBytes=logging_config['max_log_file_size_mb'] * 1024 * 1024, | |
| backupCount=logging_config['backup_count'] | |
| ) | |
| file_handler.setLevel(root_logger.level) | |
| file_handler.setFormatter(formatter) | |
| root_logger.addHandler(file_handler) | |
| logger.info(f"Logging configured: level={logging_config['level']}") | |
| except Exception as e: | |
| # Fallback to basic logging configuration | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
| ) | |
| logger.warning(f"Failed to configure logging from config, using defaults: {e}") | |
| def create_configured_container(config_file: Optional[str] = None) -> DependencyContainer: | |
| """ | |
| Create and configure a complete dependency injection container. | |
| This is the main entry point for setting up the application's dependency injection. | |
| Args: | |
| config_file: Optional path to configuration file | |
| Returns: | |
| DependencyContainer: Fully configured container | |
| """ | |
| try: | |
| logger.info("Creating configured container...") | |
| # Setup container | |
| logger.info("Setting up container...") | |
| container = setup_container(config_file) | |
| logger.info("Container setup completed") | |
| # Configure logging | |
| logger.info("Configuring logging...") | |
| config = container.resolve(AppConfig) | |
| configure_logging(config) | |
| logger.info("Logging configuration completed") | |
| # Validate container setup | |
| logger.info("Starting container validation...") | |
| try: | |
| _validate_container_setup(container) | |
| logger.info("Container validation completed") | |
| except Exception as validation_error: | |
| logger.error(f"Container validation failed: {validation_error}", exception=validation_error) | |
| # For now, let's continue even if validation fails to see if the app works | |
| logger.warning("Continuing despite validation failure...") | |
| logger.info("Application container created and configured successfully") | |
| return container | |
| except Exception as e: | |
| logger.error(f"Failed to create configured container: {e}", exception=e) | |
| raise | |
| def _validate_container_setup(container: DependencyContainer) -> None: | |
| """ | |
| Validate that the container is properly set up. | |
| Args: | |
| container: Container to validate | |
| Raises: | |
| RuntimeError: If validation fails | |
| """ | |
| logger.info("Validating container setup") | |
| required_services = [ | |
| AppConfig, | |
| TTSProviderFactory, | |
| STTProviderFactory, | |
| TranslationProviderFactory, | |
| IAudioProcessingService, | |
| AudioProcessingApplicationService, | |
| ConfigurationApplicationService, | |
| ISpeechSynthesisService, | |
| ISpeechRecognitionService, | |
| ITranslationService | |
| ] | |
| missing_services = [] | |
| logger.info("Checking service registrations...") | |
| for service_type in required_services: | |
| logger.info(f"Checking registration for: {service_type.__name__}") | |
| if not container.is_registered(service_type): | |
| missing_services.append(service_type.__name__) | |
| logger.error(f"Service not registered: {service_type.__name__}") | |
| else: | |
| logger.info(f"Service registered: {service_type.__name__}") | |
| if missing_services: | |
| error_msg = f"Container validation failed. Missing services: {missing_services}" | |
| logger.error(error_msg) | |
| raise RuntimeError(error_msg) | |
| # Test service resolution | |
| logger.info("Testing service resolution...") | |
| try: | |
| logger.info("Resolving AppConfig...") | |
| config = container.resolve(AppConfig) | |
| logger.info("AppConfig resolved successfully") | |
| logger.info("Resolving AudioProcessingApplicationService...") | |
| app_service = container.resolve(AudioProcessingApplicationService) | |
| logger.info("AudioProcessingApplicationService resolved successfully") | |
| logger.info("Resolving ConfigurationApplicationService...") | |
| config_service = container.resolve(ConfigurationApplicationService) | |
| logger.info("ConfigurationApplicationService resolved successfully") | |
| logger.info("Container validation successful") | |
| except Exception as e: | |
| error_msg = f"Container validation failed during service resolution: {e}" | |
| logger.error(error_msg, exception=e) | |
| raise RuntimeError(error_msg) | |
| def get_service_registry_info(container: DependencyContainer) -> dict: | |
| """ | |
| Get information about registered services in the container. | |
| Args: | |
| container: Container to inspect | |
| Returns: | |
| dict: Service registry information | |
| """ | |
| try: | |
| registered_services = container.get_registered_services() | |
| # Get provider availability | |
| config = container.resolve(AppConfig) | |
| tts_factory = container.resolve(TTSProviderFactory) | |
| stt_factory = container.resolve(STTProviderFactory) | |
| translation_factory = container.resolve(TranslationProviderFactory) | |
| provider_info = { | |
| 'tts_providers': tts_factory.get_available_providers(), | |
| 'stt_providers': stt_factory.get_available_providers(), | |
| 'translation_providers': [p.value for p in translation_factory.get_available_providers()] | |
| } | |
| return { | |
| 'registered_services': registered_services, | |
| 'provider_availability': provider_info, | |
| 'configuration_summary': { | |
| 'config_file': config.config_file, | |
| 'temp_dir': config.processing.temp_dir, | |
| 'log_level': config.logging.level, | |
| 'tts_preferred_providers': config.tts.preferred_providers, | |
| 'stt_default_model': config.stt.default_model, | |
| 'translation_default_provider': config.translation.default_provider | |
| } | |
| } | |
| except Exception as e: | |
| logger.error(f"Failed to get service registry info: {e}") | |
| return { | |
| 'error': str(e), | |
| 'registered_services': container.get_registered_services() if container else {} | |
| } | |
| # Global container instance management | |
| _global_container: Optional[DependencyContainer] = None | |
| def initialize_global_container(config_file: Optional[str] = None) -> DependencyContainer: | |
| """ | |
| Initialize the global container instance. | |
| Args: | |
| config_file: Optional configuration file path | |
| Returns: | |
| DependencyContainer: Global container instance | |
| """ | |
| global _global_container | |
| if _global_container is not None: | |
| logger.warning("Global container already initialized, cleaning up previous instance") | |
| _global_container.cleanup() | |
| _global_container = create_configured_container(config_file) | |
| logger.info("Global container initialized") | |
| return _global_container | |
| def get_global_container() -> DependencyContainer: | |
| """ | |
| Get the global container instance. | |
| Returns: | |
| DependencyContainer: Global container instance | |
| Raises: | |
| RuntimeError: If container is not initialized | |
| """ | |
| global _global_container | |
| if _global_container is None: | |
| logger.info("Global container not initialized, creating with defaults") | |
| _global_container = create_configured_container() | |
| return _global_container | |
| def cleanup_global_container() -> None: | |
| """Cleanup the global container instance.""" | |
| global _global_container | |
| if _global_container is not None: | |
| _global_container.cleanup() | |
| _global_container = None | |
| logger.info("Global container cleaned up") |