Spaces:
Sleeping
Sleeping
| """ | |
| Base Service Infrastructure | |
| Provides the foundation for plug-and-play services in the API gateway. | |
| All services (auth, credit, gemini, etc.) extend this base infrastructure. | |
| Core Components: | |
| - BaseService: Abstract base class for all services | |
| - ServiceConfig: Configuration container | |
| - ServiceRegistry: Global registry for service discovery | |
| - MiddlewareProtocol: Type definition for middleware functions | |
| Usage: | |
| class MyService(BaseService): | |
| @classmethod | |
| def register(cls, **config): | |
| # Service-specific registration | |
| pass | |
| @classmethod | |
| def get_middleware(cls): | |
| # Return middleware function if needed | |
| return MyMiddleware() | |
| """ | |
| import logging | |
| from abc import ABC, abstractmethod | |
| from typing import Dict, Type, Optional, Callable, Any | |
| from starlette.middleware.base import BaseHTTPMiddleware | |
| logger = logging.getLogger(__name__) | |
| class ServiceConfig: | |
| """ | |
| Base configuration container for services. | |
| Services can extend this to add their specific configuration. | |
| """ | |
| def __init__(self, **kwargs): | |
| """Initialize configuration with arbitrary key-value pairs.""" | |
| self._config = kwargs | |
| def get(self, key: str, default: Any = None) -> Any: | |
| """Get configuration value.""" | |
| return self._config.get(key, default) | |
| def set(self, key: str, value: Any) -> None: | |
| """Set configuration value.""" | |
| self._config[key] = value | |
| def __getitem__(self, key: str) -> Any: | |
| """Dictionary-style access.""" | |
| return self._config[key] | |
| def __setitem__(self, key: str, value: Any) -> None: | |
| """Dictionary-style assignment.""" | |
| self._config[key] = value | |
| def __contains__(self, key: str) -> bool: | |
| """Check if key exists.""" | |
| return key in self._config | |
| class BaseService(ABC): | |
| """ | |
| Abstract base class for all plug-and-play services. | |
| Services must implement: | |
| - register(): Register service configuration at startup | |
| - get_middleware(): Return middleware if service needs request interception | |
| - on_shutdown(): Cleanup on app shutdown | |
| """ | |
| # Service name (override in subclass) | |
| SERVICE_NAME: str = "base_service" | |
| # Service configuration | |
| _config: Optional[ServiceConfig] = None | |
| # Registration state | |
| _registered: bool = False | |
| def register(cls, **config) -> None: | |
| """ | |
| Register service configuration at application startup. | |
| Args: | |
| **config: Service-specific configuration parameters | |
| Raises: | |
| RuntimeError: If service is already registered | |
| """ | |
| if cls._registered: | |
| raise RuntimeError(f"{cls.SERVICE_NAME} is already registered") | |
| cls._config = ServiceConfig(**config) | |
| cls._registered = True | |
| logger.info(f"✅ {cls.SERVICE_NAME} registered successfully") | |
| def get_middleware(cls) -> Optional[BaseHTTPMiddleware]: | |
| """ | |
| Return middleware instance if service needs request interception. | |
| Returns: | |
| Middleware instance or None if service doesn't need middleware | |
| """ | |
| return None | |
| def on_shutdown(cls) -> None: | |
| """ | |
| Cleanup hook called during application shutdown. | |
| Override this to perform cleanup (close connections, save state, etc.) | |
| """ | |
| pass | |
| def is_registered(cls) -> bool: | |
| """Check if service has been registered.""" | |
| return cls._registered | |
| def assert_registered(cls) -> None: | |
| """ | |
| Assert that service has been registered. | |
| Raises: | |
| RuntimeError: If service is not registered | |
| """ | |
| if not cls._registered: | |
| raise RuntimeError( | |
| f"{cls.SERVICE_NAME} is not registered. " | |
| f"Call {cls.SERVICE_NAME}.register() at application startup." | |
| ) | |
| def get_config(cls) -> ServiceConfig: | |
| """ | |
| Get service configuration. | |
| Returns: | |
| ServiceConfig instance | |
| Raises: | |
| RuntimeError: If service is not registered | |
| """ | |
| cls.assert_registered() | |
| return cls._config | |
| class ServiceRegistry: | |
| """ | |
| Global registry for service discovery and management. | |
| Tracks all registered services and provides lookup functionality. | |
| """ | |
| _services: Dict[str, Type[BaseService]] = {} | |
| def register_service(cls, service_class: Type[BaseService]) -> None: | |
| """ | |
| Register a service class in the global registry. | |
| Args: | |
| service_class: Service class to register | |
| """ | |
| service_name = service_class.SERVICE_NAME | |
| if service_name in cls._services: | |
| logger.warning(f"Service '{service_name}' already registered, overwriting") | |
| cls._services[service_name] = service_class | |
| logger.debug(f"Registered service: {service_name}") | |
| def get_service(cls, service_name: str) -> Optional[Type[BaseService]]: | |
| """ | |
| Get a service class by name. | |
| Args: | |
| service_name: Name of the service to retrieve | |
| Returns: | |
| Service class or None if not found | |
| """ | |
| return cls._services.get(service_name) | |
| def get_all_services(cls) -> Dict[str, Type[BaseService]]: | |
| """ | |
| Get all registered services. | |
| Returns: | |
| Dictionary mapping service names to service classes | |
| """ | |
| return cls._services.copy() | |
| def get_all_middleware(cls) -> list: | |
| """ | |
| Get middleware from all registered services. | |
| Returns: | |
| List of middleware instances in registration order | |
| """ | |
| middleware_list = [] | |
| for service_name, service_class in cls._services.items(): | |
| if service_class.is_registered(): | |
| middleware = service_class.get_middleware() | |
| if middleware: | |
| middleware_list.append(middleware) | |
| logger.debug(f"Added middleware from service: {service_name}") | |
| return middleware_list | |
| def shutdown_all(cls) -> None: | |
| """ | |
| Call shutdown hooks for all registered services. | |
| """ | |
| logger.info("Shutting down all services...") | |
| for service_name, service_class in cls._services.items(): | |
| try: | |
| service_class.on_shutdown() | |
| logger.debug(f"Shutdown complete: {service_name}") | |
| except Exception as e: | |
| logger.error(f"Error shutting down {service_name}: {e}") | |
| logger.info("All services shut down") | |
| __all__ = [ | |
| 'BaseService', | |
| 'ServiceConfig', | |
| 'ServiceRegistry', | |
| ] | |