From 11c10ea783bdd692b58d99c86a13572a89f4aac7 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:44:13 +0800 Subject: [PATCH] fix(event): improve handler enablement check mechanism --- app/core/event.py | 57 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/app/core/event.py b/app/core/event.py index 7b87b569..90dd5237 100644 --- a/app/core/event.py +++ b/app/core/event.py @@ -6,13 +6,14 @@ import threading import time import traceback import uuid -from queue import PriorityQueue, Empty -from typing import Callable, Dict, List, Union, Optional +from functools import lru_cache +from queue import Empty, PriorityQueue +from typing import Callable, Dict, List, Optional, Union from app.helper.message import MessageHelper from app.helper.thread import ThreadHelper from app.log import logger -from app.schemas.types import EventType, ChainEventType +from app.schemas.types import ChainEventType, EventType from app.utils.limit import ExponentialBackoffRateLimiter from app.utils.singleton import Singleton @@ -254,24 +255,46 @@ class EventManager(metaclass=Singleton): handler_info.append(handler_dict) return handler_info - @staticmethod - def __get_handler_identifier(target: Union[Callable, type]) -> str: + @classmethod + @lru_cache(maxsize=1000) + def __get_handler_identifier(cls, target: Union[Callable, type]) -> Optional[str]: """ - 获取处理器或处理器类的唯一标识符,包括模块名和类名 + 获取处理器或处理器类的唯一标识符,包括模块名和类名/方法名 :param target: 处理器函数或类 :return: 唯一标识符 """ - if isinstance(target, type): - # 如果是类,使用模块名和类名 - module_name = target.__module__ - class_name = target.__qualname__ - return f"{module_name}.{class_name}" - else: - # 如果是函数或方法,使用 inspect.getmodule 来获取模块名 - module = inspect.getmodule(target) + # 统一使用 inspect.getmodule 来获取模块名 + module = inspect.getmodule(target) + module_name = module.__name__ if module else "unknown_module" + + # 使用 __qualname__ 获取目标的限定名 + qualname = target.__qualname__ + return f"{module_name}.{qualname}" + + @classmethod + @lru_cache(maxsize=1000) + def __get_class_from_callable(cls, handler: Callable) -> Optional[str]: + """ + 获取可调用对象所属类的唯一标识符 + :param handler: 可调用对象(函数、方法等) + :return: 类的唯一标识符 + """ + # 对于绑定方法,通过 __self__.__class__ 获取类 + if inspect.ismethod(handler) and hasattr(handler, "__self__"): + return cls.__get_handler_identifier(handler.__self__.__class__) + + # 对于类实例(实现了 __call__ 方法) + if not inspect.isfunction(handler) and hasattr(handler, "__call__"): + handler_cls = handler.__class__ + return cls.__get_handler_identifier(handler_cls) + + # 对于未绑定方法、静态方法、类方法,使用 __qualname__ 提取类信息 + qualname_parts = handler.__qualname__.split(".") + if len(qualname_parts) > 1: + class_name = ".".join(qualname_parts[:-1]) + module = inspect.getmodule(handler) module_name = module.__name__ if module else "unknown_module" - qualname = target.__qualname__ - return f"{module_name}.{qualname}" + return f"{module_name}.{class_name}" def __is_handler_enabled(self, handler: Callable) -> bool: """ @@ -283,7 +306,7 @@ class EventManager(metaclass=Singleton): handler_id = self.__get_handler_identifier(handler) # 获取处理器所属类的唯一标识符 - class_id = self.__get_handler_identifier(handler.__self__.__class__) if hasattr(handler, '__self__') else None + class_id = self.__get_class_from_callable(handler) # 检查处理器或类是否被禁用,只要其中之一被禁用则返回 False if handler_id in self.__disabled_handlers or (class_id is not None and class_id in self.__disabled_classes):