from abc import abstractmethod, ABC from typing import Generic, Optional, TypeVar from pydantic import BaseModel from pydantic_settings.main import asyncio class HealthStatus(BaseModel): """ 服务健康状态类 """ service_name: str is_initialized: bool = False is_healthy: bool = False detail: Optional[str] = None T = TypeVar("T", bound="BaseService") class BaseService(ABC, Generic[T]): """ 基础服务类,定义了服务的基本状态和操作 """ _lock: asyncio.Lock = asyncio.Lock() _instance: Optional[T] = None @property @abstractmethod def service_name(self) -> str: """ 返回服务名称 """ @abstractmethod async def _initialize(self) -> T: """ 初始化服务 """ @abstractmethod async def _shutdown(self) -> None: """ 关闭服务 """ @abstractmethod async def _health_check(self) -> bool: """ 健康检查服务 """ async def check_health(self) -> HealthStatus: """ 检查服务健康状态 """ async with self._lock: if self._instance is None: return HealthStatus( service_name=self.service_name, is_initialized=False, is_healthy=False, ) try: is_healthy = await self._health_check() return HealthStatus( service_name=self.service_name, is_initialized=True, is_healthy=is_healthy, detail="success", ) except Exception as e: return HealthStatus( service_name=self.service_name, is_initialized=True, is_healthy=False, detail=str(e), ) async def initialize(self) -> None: """ 初始化服务 """ async with self._lock: if self._instance is not None: await self._shutdown() try: self._instance = await self._initialize() except Exception as e: self._instance = None raise e async def shutdown(self) -> None: """ 关闭服务 """ async with self._lock: if self._instance is None: return await self._shutdown() self._instance = None async def get_instance(self, force_initialize: bool = False) -> T: """ 获取服务实例 """ if self._instance is None and force_initialize: await self.initialize() if self._instance is None: raise ValueError(f"Service {self.service_name} is not initialized.") return self._instance __all__ = [ "BaseService", "HealthStatus", ]