first commit
This commit is contained in:
112
servers/base.py
Normal file
112
servers/base.py
Normal file
@@ -0,0 +1,112 @@
|
||||
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",
|
||||
]
|
||||
59
servers/database/server.py
Normal file
59
servers/database/server.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from typing import Optional
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
from pydantic import Field
|
||||
|
||||
from servers.base import BaseService
|
||||
from sqlmodel import create_engine
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from sqlalchemy import Engine
|
||||
|
||||
class DatabaseSettings(BaseSettings):
|
||||
"""
|
||||
数据库服务配置类
|
||||
"""
|
||||
model_config = SettingsConfigDict(
|
||||
env_prefix="database_",
|
||||
case_sensitive=False,
|
||||
extra="ignore",
|
||||
)
|
||||
url: Optional[str] = Field(None, description="数据库连接URL")
|
||||
|
||||
class DatabaseService(BaseService[Engine]):
|
||||
"""
|
||||
数据库服务类,定义了数据库服务的基本状态和操作
|
||||
"""
|
||||
service_name: str = "database"
|
||||
|
||||
async def _initialize(self) -> Engine:
|
||||
"""
|
||||
初始化数据库服务
|
||||
"""
|
||||
setting = DatabaseSettings()
|
||||
if not setting.url:
|
||||
raise ValueError("数据库连接URL不能为空")
|
||||
engine = create_engine(setting.url)
|
||||
return engine
|
||||
|
||||
async def _shutdown(self) -> None:
|
||||
"""
|
||||
关闭数据库服务
|
||||
"""
|
||||
if not self._instance:
|
||||
return
|
||||
self._instance.dispose()
|
||||
|
||||
async def _check_health(self) -> bool:
|
||||
"""
|
||||
检查数据库服务健康状态
|
||||
"""
|
||||
if not self._instance:
|
||||
return False
|
||||
async with AsyncSession(self._instance) as session:
|
||||
await session.exec("SELECT 1")
|
||||
return True
|
||||
|
||||
database_service = DatabaseService()
|
||||
|
||||
__all__ = [
|
||||
"database_service",
|
||||
]
|
||||
66
servers/redis/server.py
Normal file
66
servers/redis/server.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from typing import Optional
|
||||
from pydantic import Field
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
from redis.asyncio import Redis
|
||||
from servers.base import BaseService
|
||||
|
||||
class RedisSettings(BaseSettings):
|
||||
"""
|
||||
Redis服务配置类
|
||||
"""
|
||||
model_config = SettingsConfigDict(
|
||||
env_prefix="redis_",
|
||||
case_sensitive=False,
|
||||
extra="ignore",
|
||||
)
|
||||
url: Optional[str] = Field(None, description="Redis连接URL")
|
||||
host: Optional[str] = Field(None, description="Redis主机地址")
|
||||
port: Optional[int] = Field(6379, description="Redis端口号")
|
||||
db: Optional[int] = Field(0, description="Redis数据库索引")
|
||||
password: Optional[str] = Field(None, description="Redis密码")
|
||||
|
||||
class RedisService(BaseService[Redis]):
|
||||
"""
|
||||
Redis服务类,定义了Redis服务的基本状态和操作
|
||||
"""
|
||||
service_name: str = "redis"
|
||||
async def _initialize(self) -> Redis:
|
||||
"""
|
||||
初始化Redis服务
|
||||
"""
|
||||
setting = RedisSettings()
|
||||
if not setting.url or not setting.host:
|
||||
raise ValueError("Redis连接URL或主机地址不能为空")
|
||||
|
||||
if setting.url:
|
||||
return Redis.from_url(setting.url)
|
||||
return Redis(
|
||||
host=setting.host,
|
||||
port=setting.port,
|
||||
db=setting.db,
|
||||
password=setting.password,
|
||||
)
|
||||
|
||||
async def _shutdown(self) -> None:
|
||||
"""
|
||||
关闭Redis服务
|
||||
"""
|
||||
if not self._instance:
|
||||
return
|
||||
await self._instance.aclose()
|
||||
|
||||
async def _check_health(self) -> bool:
|
||||
"""
|
||||
检查Redis服务健康状态
|
||||
"""
|
||||
if not self._instance:
|
||||
return False
|
||||
await self._instance.ping()
|
||||
return True
|
||||
|
||||
redis_service = RedisService()
|
||||
|
||||
__all__ = [
|
||||
"redis_service",
|
||||
]
|
||||
Reference in New Issue
Block a user