bugfix:修复sqlite部分场景下锁竞争问题;新增插件恶意触发配置文件 (#2144)

* bugfix:修复sqlite部分场景下锁竞争问题;新增插件恶意触发配置文件

* 文件没同步完
This commit is contained in:
Copaan
2026-06-24 09:11:03 +08:00
committed by GitHub
parent 73cbe2a609
commit f4d2342693
39 changed files with 1577 additions and 829 deletions
+3 -28
View File
@@ -5,12 +5,10 @@ from typing_extensions import Self
from tortoise import fields
from tortoise.expressions import Q
from zhenxun.services.cache import CacheException, CacheRegistry, CacheRoot
from zhenxun.services.cache.runtime_cache import BanMemoryCache
from zhenxun.services.data_access import DataAccess
from zhenxun.services.db_context import Model
from zhenxun.services.log import logger
from zhenxun.utils.enum import CacheType, DbLockType
from zhenxun.utils.enum import DbLockType
from zhenxun.utils.exception import UserAndGroupIsNone
@@ -38,28 +36,8 @@ class BanConsole(Model):
unique_together = ("user_id", "group_id")
indexes = [("user_id",), ("group_id",)] # noqa: RUF012
cache_type = CacheType.BAN
"""缓存类型"""
cache_key_field = ("user_id", "group_id")
"""缓存键字段"""
enable_lock: ClassVar[list[DbLockType]] = [DbLockType.CREATE, DbLockType.UPSERT]
"""开启锁"""
_cache_checked: ClassVar[bool] = False
@classmethod
def _ensure_cache_registered(cls):
"""兜底注册 BAN 缓存,避免启动时序导致的未注册问题。"""
if cls._cache_checked:
return
try:
CacheRoot.get_model(CacheType.BAN)
except CacheException:
CacheRegistry.register(
CacheType.BAN,
cls,
key_format="{user_id}_{group_id}",
)
cls._cache_checked = True
@classmethod
async def create(cls, *args, **kwargs) -> Self:
@@ -87,15 +65,13 @@ class BanConsole(Model):
返回:
Self | None: Self
"""
cls._ensure_cache_registered()
if not user_id and not group_id:
raise UserAndGroupIsNone()
if user_id:
dao = DataAccess(cls)
return (
await dao.safe_get_or_none(user_id=user_id, group_id=group_id)
await cls.safe_get_or_none(user_id=user_id, group_id=group_id)
if group_id
else await dao.safe_get_or_none(user_id=user_id, group_id__isnull=True)
else await cls.safe_get_or_none(user_id=user_id, group_id__isnull=True)
)
else:
return await cls.safe_get_or_none(
@@ -177,7 +153,6 @@ class BanConsole(Model):
)
if not user_id and not group_id:
raise UserAndGroupIsNone()
cls._ensure_cache_registered()
target, _ = await cls.update_or_create(
user_id=user_id,
group_id=group_id,
+8 -12
View File
@@ -9,10 +9,9 @@ from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.task_info import TaskInfo
from zhenxun.services.cache import CacheRoot
from zhenxun.services.cache.runtime_cache import GroupMemoryCache
from zhenxun.services.data_access import DataAccess
from zhenxun.services.db_context import Model
from zhenxun.services.db_context.schema_ops import AlterColumnType, CreateIndex
from zhenxun.utils.enum import CacheType, DbLockType, PluginType
from zhenxun.utils.enum import DbLockType, PluginType
if TYPE_CHECKING:
from zhenxun.services.cache.runtime_cache import GroupSnapshot
@@ -98,10 +97,6 @@ class GroupConsole(Model):
("group_id",)
]
cache_type = CacheType.GROUPS
"""缓存类型"""
cache_key_field = ("group_id", "channel_id")
"""缓存键字段"""
enable_lock: ClassVar[list[DbLockType]] = [DbLockType.CREATE, DbLockType.UPSERT]
"""开启锁"""
_root_group_locks: ClassVar[dict[str, asyncio.Lock]] = {}
@@ -331,9 +326,11 @@ class GroupConsole(Model):
if update_fields:
await keep.save(update_fields=update_fields)
for group in groups:
if group.id != keep.id:
await group.delete()
duplicate_ids = [
group.id for group in groups if group.id and group.id != keep.id
]
if duplicate_ids:
await cls.filter(id__in=duplicate_ids).delete()
await GroupMemoryCache.upsert_from_model(keep)
return keep
@@ -417,14 +414,13 @@ class GroupConsole(Model):
clean_duplicates: bool = True,
) -> Self | None:
"""获取群组(数据库)"""
dao = DataAccess(cls)
if channel_id:
return await dao.safe_get_or_none(
return await cls.safe_get_or_none(
group_id=group_id,
channel_id=channel_id,
clean_duplicates=clean_duplicates,
)
return await dao.safe_get_or_none(
return await cls.safe_get_or_none(
group_id=group_id,
channel_id__isnull=True,
clean_duplicates=clean_duplicates,
-6
View File
@@ -1,7 +1,6 @@
from tortoise import fields
from zhenxun.services.db_context import Model
from zhenxun.utils.enum import CacheType
class GroupPluginSetting(Model):
@@ -18,11 +17,6 @@ class GroupPluginSetting(Model):
updated_at = fields.DatetimeField(auto_now=True, description="最后更新时间")
"""最后更新时间"""
cache_type = CacheType.GROUP_PLUGIN_SETTINGS
"""缓存类型"""
cache_key_field = ("group_id", "plugin_name")
"""缓存键字段"""
class Meta: # pyright: ignore [reportIncompatibleVariableOverride]
table = "group_plugin_settings"
table_description = "插件分群通用配置表"