first commit

This commit is contained in:
2026-02-06 17:21:11 +08:00
commit 16d03c47d3
9 changed files with 716 additions and 0 deletions

112
servers/base.py Normal file
View 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",
]

View 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
View 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",
]