mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-07 12:50:03 +08:00
bugfix:修复命令前缀判断问题、修复超级用户无法豁免问题 (#2141)
* bugfix:修复命令前缀判断问题、修复超级用户无法豁免问题 * bugfix:修复格式问题
This commit is contained in:
+29
-9
@@ -74,8 +74,12 @@ class BoundedTTLCache(Generic[K, V]):
|
||||
self._sets = 0
|
||||
self._evictions = 0
|
||||
self._lock = asyncio.Lock()
|
||||
self._last_sweep = 0.0
|
||||
self.__class__._instances.add(self)
|
||||
|
||||
# 全量过期清理的最小间隔(B1):避免每次 get 都 O(N) 扫描整表。
|
||||
_SWEEP_INTERVAL = 30.0
|
||||
|
||||
def _expire_at(self, now: float) -> float:
|
||||
if self._ttl_seconds <= 0:
|
||||
return sys.float_info.max
|
||||
@@ -106,23 +110,37 @@ class BoundedTTLCache(Generic[K, V]):
|
||||
self._evictions += 1
|
||||
return True
|
||||
|
||||
def _cleanup_nolock(self, now: float) -> None:
|
||||
expired_keys = [
|
||||
key for key, (expire_at, _, _) in self._cache.items() if expire_at <= now
|
||||
]
|
||||
for key in expired_keys:
|
||||
if self._remove_key_nolock(key):
|
||||
self._evictions += 1
|
||||
def _enforce_capacity_nolock(self) -> None:
|
||||
"""容量边界强制(O(溢出量)):仅在新增后调用,不扫描全表。"""
|
||||
while len(self._cache) > self._max_items:
|
||||
self._pop_oldest_nolock()
|
||||
if self._max_total_bytes is not None:
|
||||
while self._total_bytes > self._max_total_bytes and self._cache:
|
||||
self._pop_oldest_nolock()
|
||||
|
||||
def _sweep_expired_nolock(self, now: float) -> None:
|
||||
"""全量过期清理(O(N)):由节流器或后台/governor 低频触发。"""
|
||||
self._last_sweep = now
|
||||
expired_keys = [
|
||||
key for key, (expire_at, _, _) in self._cache.items() if expire_at <= now
|
||||
]
|
||||
for key in expired_keys:
|
||||
if self._remove_key_nolock(key):
|
||||
self._evictions += 1
|
||||
|
||||
def _maybe_sweep_nolock(self, now: float) -> None:
|
||||
if now - self._last_sweep >= self._SWEEP_INTERVAL:
|
||||
self._sweep_expired_nolock(now)
|
||||
|
||||
def _cleanup_nolock(self, now: float) -> None:
|
||||
"""完整清理(全量过期 + 容量):保留给 stats / 显式调用。"""
|
||||
self._sweep_expired_nolock(now)
|
||||
self._enforce_capacity_nolock()
|
||||
|
||||
async def get(self, key: K) -> V | None:
|
||||
now = time.monotonic()
|
||||
async with self._lock:
|
||||
self._cleanup_nolock(now)
|
||||
# 仅做命中项的单条过期检查(O(1)),全量清理改为低频节流(B1)。
|
||||
item = self._cache.get(key)
|
||||
if item is None:
|
||||
self._misses += 1
|
||||
@@ -148,7 +166,9 @@ class BoundedTTLCache(Generic[K, V]):
|
||||
self._total_bytes += value_size
|
||||
self._sets += 1
|
||||
self._cache.move_to_end(key)
|
||||
self._cleanup_nolock(now)
|
||||
# 新增后必做容量强制(廉价);全量过期清理走低频节流(B1)。
|
||||
self._maybe_sweep_nolock(now)
|
||||
self._enforce_capacity_nolock()
|
||||
return key in self._cache
|
||||
|
||||
async def delete(self, key: K) -> bool:
|
||||
|
||||
@@ -146,6 +146,10 @@ class DataAccess(Generic[T]):
|
||||
返回:
|
||||
str | None: 缓存键,如果无法构建则返回None
|
||||
"""
|
||||
# 含 ORM lookup 后缀(如 channel_id__isnull / x__gte)的查询无法可靠映射到
|
||||
# 单条主键缓存键,退化为直查 DB,避免空串与 NULL 语义混淆导致错误命中(A5)。
|
||||
if any("__" in key for key in kwargs):
|
||||
return None
|
||||
if isinstance(self.key_field, tuple):
|
||||
# 多字段主键
|
||||
key_parts = []
|
||||
|
||||
@@ -278,6 +278,7 @@ async def _execute_single_job_instance(
|
||||
schedule_id=schedule.id,
|
||||
plugin_name=plugin_name,
|
||||
bot_id=bot.self_id,
|
||||
platform_scope=PlatformUtils.get_platform_scope(bot),
|
||||
group_id=group_id,
|
||||
job_kwargs=schedule.job_kwargs if isinstance(schedule.job_kwargs, dict) else {},
|
||||
)
|
||||
@@ -381,6 +382,7 @@ async def _execute_job(
|
||||
)
|
||||
if bot is None:
|
||||
return
|
||||
context_override.platform_scope = PlatformUtils.get_platform_scope(bot)
|
||||
logger.info(f"开始执行临时任务: {plugin_name}")
|
||||
injected_params = {"context": context_override}
|
||||
state: T_State = {ScheduleContext: context_override}
|
||||
|
||||
@@ -82,6 +82,7 @@ async def _load_schedules_from_db():
|
||||
schedule_id=0,
|
||||
plugin_name=job_id,
|
||||
bot_id=None,
|
||||
platform_scope=None,
|
||||
group_id=None,
|
||||
job_kwargs={},
|
||||
)
|
||||
|
||||
@@ -250,6 +250,7 @@ class SchedulerManager:
|
||||
schedule_id=0,
|
||||
plugin_name=f"runtime::{func.__module__}",
|
||||
bot_id=None,
|
||||
platform_scope=None,
|
||||
group_id=None,
|
||||
job_kwargs={},
|
||||
)
|
||||
|
||||
@@ -105,6 +105,7 @@ class ScheduleContext(BaseModel):
|
||||
schedule_id: int = Field(..., description="数据库中的任务ID")
|
||||
plugin_name: str = Field(..., description="任务所属的插件名称")
|
||||
bot_id: str | None = Field(None, description="执行任务的Bot ID")
|
||||
platform_scope: str | None = Field(None, description="执行任务的细粒度平台作用域")
|
||||
group_id: str | None = Field(None, description="当前执行实例的目标群组ID")
|
||||
job_kwargs: dict = Field(default_factory=dict, description="任务配置的参数")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user