mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
✨ feat(cache): 增加缓存功能配置项,并新增数据访问层以支持缓存逻辑
This commit is contained in:
parent
811089b3d7
commit
7d962bb4a8
@ -26,6 +26,8 @@ driver = nonebot.get_driver()
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
enable_cache: bool = True
|
||||
"""是否开启缓存功能"""
|
||||
redis_host: str | None = None
|
||||
"""redis地址"""
|
||||
redis_port: int | None = None
|
||||
|
||||
210
zhenxun/services/data_access.py
Normal file
210
zhenxun/services/data_access.py
Normal file
@ -0,0 +1,210 @@
|
||||
from typing import Any, Generic, TypeVar, cast
|
||||
|
||||
from zhenxun.services.cache import CacheRoot
|
||||
from zhenxun.services.cache import config as cache_config
|
||||
from zhenxun.services.db_context import Model
|
||||
from zhenxun.services.log import logger
|
||||
|
||||
T = TypeVar("T", bound=Model)
|
||||
|
||||
|
||||
class DataAccess(Generic[T]):
|
||||
"""数据访问层,根据配置决定是否使用缓存
|
||||
|
||||
使用示例:
|
||||
```python
|
||||
from zhenxun.services import DataAccess
|
||||
from zhenxun.models.plugin_info import PluginInfo
|
||||
|
||||
# 创建数据访问对象
|
||||
plugin_dao = DataAccess(PluginInfo)
|
||||
|
||||
# 获取单个数据
|
||||
plugin = await plugin_dao.get(module="example_module")
|
||||
|
||||
# 获取所有数据
|
||||
all_plugins = await plugin_dao.all()
|
||||
|
||||
# 筛选数据
|
||||
enabled_plugins = await plugin_dao.filter(status=True)
|
||||
|
||||
# 创建数据
|
||||
new_plugin = await plugin_dao.create(
|
||||
module="new_module",
|
||||
name="新插件",
|
||||
status=True
|
||||
)
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(self, model_cls: type[T], cache_type: str | None = None):
|
||||
"""初始化数据访问对象
|
||||
|
||||
参数:
|
||||
model_cls: 模型类
|
||||
cache_type: 缓存类型,如果为None则使用模型类的cache_type属性
|
||||
"""
|
||||
self.model_cls = model_cls
|
||||
self.cache_type = cache_type or getattr(model_cls, "cache_type", None)
|
||||
|
||||
async def get_or_none(self, *args, **kwargs) -> T | None:
|
||||
"""获取单条数据
|
||||
|
||||
参数:
|
||||
*args: 查询参数
|
||||
**kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
Optional[T]: 查询结果,如果不存在返回None
|
||||
"""
|
||||
# 如果缓存功能被禁用或模型没有缓存类型,直接从数据库获取
|
||||
if not cache_config.enable_cache or not self.cache_type:
|
||||
return await self.model_cls.safe_get_or_none(*args, **kwargs)
|
||||
|
||||
# 从缓存获取
|
||||
try:
|
||||
# 生成缓存键
|
||||
key = self._generate_cache_key(kwargs)
|
||||
# 尝试从缓存获取
|
||||
data = await CacheRoot.get(self.cache_type, key)
|
||||
if data:
|
||||
return cast(T, data)
|
||||
except Exception as e:
|
||||
logger.error("从缓存获取数据失败", e=e)
|
||||
|
||||
# 如果缓存中没有,从数据库获取
|
||||
return await self.model_cls.safe_get_or_none(*args, **kwargs)
|
||||
|
||||
async def filter(self, *args, **kwargs) -> list[T]:
|
||||
"""筛选数据
|
||||
|
||||
参数:
|
||||
*args: 查询参数
|
||||
**kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
List[T]: 查询结果列表
|
||||
"""
|
||||
# 如果缓存功能被禁用或模型没有缓存类型,直接从数据库获取
|
||||
if not cache_config.enable_cache or not self.cache_type:
|
||||
return await self.model_cls.filter(*args, **kwargs)
|
||||
|
||||
# 尝试从缓存获取所有数据后筛选
|
||||
try:
|
||||
# 获取缓存数据
|
||||
cache_data = await CacheRoot.get_cache_data(self.cache_type)
|
||||
if isinstance(cache_data, dict) and cache_data:
|
||||
# 在内存中筛选
|
||||
filtered_data = []
|
||||
for item in cache_data.values():
|
||||
match = not any(
|
||||
not hasattr(item, k) or getattr(item, k) != v
|
||||
for k, v in kwargs.items()
|
||||
)
|
||||
if match:
|
||||
filtered_data.append(item)
|
||||
return cast(list[T], filtered_data)
|
||||
except Exception as e:
|
||||
logger.error("从缓存筛选数据失败", e=e)
|
||||
|
||||
# 如果缓存中没有或筛选失败,从数据库获取
|
||||
return await self.model_cls.filter(*args, **kwargs)
|
||||
|
||||
async def all(self) -> list[T]:
|
||||
"""获取所有数据
|
||||
|
||||
返回:
|
||||
List[T]: 所有数据列表
|
||||
"""
|
||||
# 如果缓存功能被禁用或模型没有缓存类型,直接从数据库获取
|
||||
if not cache_config.enable_cache or not self.cache_type:
|
||||
return await self.model_cls.all()
|
||||
|
||||
# 尝试从缓存获取所有数据
|
||||
try:
|
||||
# 获取缓存数据
|
||||
cache_data = await CacheRoot.get_cache_data(self.cache_type)
|
||||
if isinstance(cache_data, dict) and cache_data:
|
||||
return cast(list[T], list(cache_data.values()))
|
||||
except Exception as e:
|
||||
logger.error("从缓存获取所有数据失败", e=e)
|
||||
|
||||
# 如果缓存中没有,从数据库获取
|
||||
return await self.model_cls.all()
|
||||
|
||||
async def count(self, *args, **kwargs) -> int:
|
||||
"""获取数据数量
|
||||
|
||||
参数:
|
||||
*args: 查询参数
|
||||
**kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
int: 数据数量
|
||||
"""
|
||||
# 直接从数据库获取数量
|
||||
return await self.model_cls.filter(*args, **kwargs).count()
|
||||
|
||||
async def exists(self, *args, **kwargs) -> bool:
|
||||
"""判断数据是否存在
|
||||
|
||||
参数:
|
||||
*args: 查询参数
|
||||
**kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
bool: 是否存在
|
||||
"""
|
||||
# 直接从数据库判断是否存在
|
||||
return await self.model_cls.filter(*args, **kwargs).exists()
|
||||
|
||||
async def create(self, **kwargs) -> T:
|
||||
"""创建数据
|
||||
|
||||
参数:
|
||||
**kwargs: 创建参数
|
||||
|
||||
返回:
|
||||
T: 创建的数据
|
||||
"""
|
||||
return await self.model_cls.create(**kwargs)
|
||||
|
||||
async def update_or_create(
|
||||
self, defaults: dict[str, Any] | None = None, **kwargs
|
||||
) -> tuple[T, bool]:
|
||||
"""更新或创建数据
|
||||
|
||||
参数:
|
||||
defaults: 默认值
|
||||
**kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
tuple[T, bool]: (数据, 是否创建)
|
||||
"""
|
||||
return await self.model_cls.update_or_create(defaults=defaults, **kwargs)
|
||||
|
||||
async def delete(self, *args, **kwargs) -> int:
|
||||
"""删除数据
|
||||
|
||||
参数:
|
||||
*args: 查询参数
|
||||
**kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
int: 删除的数据数量
|
||||
"""
|
||||
return await self.model_cls.filter(*args, **kwargs).delete()
|
||||
|
||||
def _generate_cache_key(self, kwargs: dict[str, Any]) -> str:
|
||||
"""根据查询参数生成缓存键
|
||||
|
||||
参数:
|
||||
kwargs: 查询参数
|
||||
|
||||
返回:
|
||||
str: 缓存键
|
||||
"""
|
||||
# 实现一个简单的键生成算法
|
||||
if not kwargs:
|
||||
return "default"
|
||||
return "_".join(f"{k}:{v}" for k, v in sorted(kwargs.items()))
|
||||
Loading…
Reference in New Issue
Block a user