ErisPulse 2.4.6.dev2__tar.gz → 2.4.6.dev3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/PKG-INFO +1 -1
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/pyproject.toml +1 -1
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/base.py +7 -1
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/base.pyi +2 -1
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/command.py +1 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/adapter.py +66 -8
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/adapter.pyi +4 -1
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/constants.py +5 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/lifecycle.py +8 -2
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/lifecycle.pyi +1 -1
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/.gitignore +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/LICENSE +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/README.md +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/base.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/cli.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/cli.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/create.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/create.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/init.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/init.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/install.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/install.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list_remote.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/run.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/run.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/self_update.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/uninstall.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/upgrade.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/console.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/registry.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/display.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/display.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/package_manager.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/adapter.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/adapter.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/manager.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/module.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/module.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/storage.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/storage.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/command.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message_builder.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/meta.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/notice.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/request.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/session_type.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/session_type.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/wrapper.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/wrapper.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/config.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/config.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/constants.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/logger.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/logger.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/module.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/module.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/router.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/router.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/storage.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/storage.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__main__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/adapter.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/finder.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/finder.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/module.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/adapter.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/adapter.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/loader.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/loader.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/module.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/module.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/strategy.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/context.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/context.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/exceptions.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/exceptions.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/frame_config.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/frame_config.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/sdk.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/sdk.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/4xx.png +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/5xx.png +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/__init__.py +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/__init__.pyi +0 -0
- {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/unknow.png +0 -0
|
@@ -12,11 +12,12 @@ ErisPulse 事件处理基础模块
|
|
|
12
12
|
from .. import adapter, logger
|
|
13
13
|
from ...runtime import get_event_config
|
|
14
14
|
from ...runtime.context import current_owner
|
|
15
|
-
from ..constants import DEFAULT_HANDLER_PRIORITY, UNKNOWN_PLATFORM, EVENT_TYPE_MESSAGE
|
|
15
|
+
from ..constants import DEFAULT_HANDLER_PRIORITY, UNKNOWN_PLATFORM, EVENT_TYPE_MESSAGE, HANDLER_SLOW_THRESHOLD_SECS
|
|
16
16
|
from typing import Any
|
|
17
17
|
from collections.abc import Callable
|
|
18
18
|
import asyncio
|
|
19
19
|
import inspect
|
|
20
|
+
import time as _time
|
|
20
21
|
from itertools import groupby
|
|
21
22
|
from .wrapper import Event
|
|
22
23
|
from ..lifecycle import lifecycle
|
|
@@ -34,11 +35,16 @@ async def _invoke_handler(handler_info: dict, event: Event) -> None:
|
|
|
34
35
|
:param event: 事件对象
|
|
35
36
|
"""
|
|
36
37
|
handler = handler_info["func"]
|
|
38
|
+
_hname = getattr(handler, "__qualname__", getattr(handler, "__name__", str(handler)))
|
|
37
39
|
try:
|
|
40
|
+
_t = _time.monotonic()
|
|
38
41
|
if inspect.iscoroutinefunction(handler):
|
|
39
42
|
await handler(event)
|
|
40
43
|
else:
|
|
41
44
|
handler(event)
|
|
45
|
+
_elapsed = _time.monotonic() - _t
|
|
46
|
+
if _elapsed > HANDLER_SLOW_THRESHOLD_SECS:
|
|
47
|
+
logger.warning(f"[EventHandler] Slow handler {_hname} took {_elapsed:.4f}s")
|
|
42
48
|
except Exception as e:
|
|
43
49
|
logger.error(f"事件处理器执行错误: {e}")
|
|
44
50
|
|
|
@@ -18,11 +18,12 @@ ErisPulse 事件处理基础模块
|
|
|
18
18
|
from .. import adapter, logger
|
|
19
19
|
from ...runtime import get_event_config
|
|
20
20
|
from ...runtime.context import current_owner
|
|
21
|
-
from ..constants import DEFAULT_HANDLER_PRIORITY, UNKNOWN_PLATFORM, EVENT_TYPE_MESSAGE
|
|
21
|
+
from ..constants import DEFAULT_HANDLER_PRIORITY, UNKNOWN_PLATFORM, EVENT_TYPE_MESSAGE, HANDLER_SLOW_THRESHOLD_SECS
|
|
22
22
|
from typing import Any
|
|
23
23
|
from collections.abc import Callable
|
|
24
24
|
import asyncio
|
|
25
25
|
import inspect
|
|
26
|
+
import time as _time
|
|
26
27
|
from itertools import groupby
|
|
27
28
|
from .wrapper import Event
|
|
28
29
|
from ..lifecycle import lifecycle
|
|
@@ -23,6 +23,7 @@ from .constants import (
|
|
|
23
23
|
CONFIG_KEY_ADAPTER_STATUS,
|
|
24
24
|
CONFIG_KEY_ADAPTER_STATUS_OF,
|
|
25
25
|
DEFAULT_ADAPTER_ENABLED,
|
|
26
|
+
HANDLER_SLOW_THRESHOLD_SECS,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
|
|
@@ -685,6 +686,9 @@ class AdapterManager(ManagerBase):
|
|
|
685
686
|
"""
|
|
686
687
|
提交OneBot12协议事件到指定平台
|
|
687
688
|
|
|
689
|
+
每个事件处理器(handler)都在独立的 asyncio.Task 中执行,
|
|
690
|
+
单个处理器阻塞不会影响框架的事件分发和其他处理器运行。
|
|
691
|
+
|
|
688
692
|
:param data: 符合OneBot12标准的事件数据
|
|
689
693
|
|
|
690
694
|
:example:
|
|
@@ -766,7 +770,7 @@ class AdapterManager(ManagerBase):
|
|
|
766
770
|
},
|
|
767
771
|
)
|
|
768
772
|
|
|
769
|
-
# 先执行OneBot12
|
|
773
|
+
# 先执行OneBot12中间件(中间件可以修改数据,必须顺序执行)
|
|
770
774
|
processed_data = data
|
|
771
775
|
for middleware in self._onebot_middlewares:
|
|
772
776
|
result = await middleware(processed_data)
|
|
@@ -777,7 +781,7 @@ class AdapterManager(ManagerBase):
|
|
|
777
781
|
f"中间件 {middleware.__qualname__} 返回 None,已忽略并保留原数据"
|
|
778
782
|
)
|
|
779
783
|
|
|
780
|
-
# 分发到OneBot12
|
|
784
|
+
# 分发到OneBot12事件处理器(每个 handler 在独立 Task 中执行,不阻塞框架)
|
|
781
785
|
handlers_to_call = []
|
|
782
786
|
|
|
783
787
|
# 处理特定事件类型的处理器
|
|
@@ -787,12 +791,14 @@ class AdapterManager(ManagerBase):
|
|
|
787
791
|
# 处理通配符处理器
|
|
788
792
|
handlers_to_call.extend(self._onebot_handlers.get("*", []))
|
|
789
793
|
|
|
790
|
-
#
|
|
794
|
+
# 将符合条件的处理器分发到独立 Task
|
|
791
795
|
for handler_wrapper in handlers_to_call:
|
|
792
796
|
handler_platform = handler_wrapper.get("platform")
|
|
793
|
-
# 如果处理器没有指定平台,或者指定的平台与当前事件平台匹配
|
|
794
797
|
if handler_platform is None or handler_platform == platform:
|
|
795
|
-
|
|
798
|
+
self._dispatch_handler_task(
|
|
799
|
+
handler_wrapper["func"], processed_data,
|
|
800
|
+
event_type=event_type, platform=platform,
|
|
801
|
+
)
|
|
796
802
|
|
|
797
803
|
# 只有当存在原生事件数据时才分发原生事件
|
|
798
804
|
if raw_event_type and (platform_raw := data.get(f"{platform}_raw")) is not None:
|
|
@@ -805,12 +811,14 @@ class AdapterManager(ManagerBase):
|
|
|
805
811
|
# 处理原生事件的通配符处理器
|
|
806
812
|
raw_handlers_to_call.extend(self._raw_handlers.get("*", []))
|
|
807
813
|
|
|
808
|
-
#
|
|
814
|
+
# 将符合条件的原生事件处理器分发到独立 Task
|
|
809
815
|
for handler_wrapper in raw_handlers_to_call:
|
|
810
816
|
handler_platform = handler_wrapper.get("platform")
|
|
811
|
-
# 如果处理器没有指定平台,或者指定的平台与当前事件平台匹配
|
|
812
817
|
if handler_platform is None or handler_platform == platform:
|
|
813
|
-
|
|
818
|
+
self._dispatch_handler_task(
|
|
819
|
+
handler_wrapper["func"], platform_raw,
|
|
820
|
+
event_type=raw_event_type, platform=platform,
|
|
821
|
+
)
|
|
814
822
|
|
|
815
823
|
# 钩子: 事件分发完成
|
|
816
824
|
await lifecycle.emit("adapter.event.dispatched", {
|
|
@@ -820,6 +828,56 @@ class AdapterManager(ManagerBase):
|
|
|
820
828
|
"onebot_handlers_count": len(handlers_to_call),
|
|
821
829
|
})
|
|
822
830
|
|
|
831
|
+
def _dispatch_handler_task(
|
|
832
|
+
self,
|
|
833
|
+
func: Callable,
|
|
834
|
+
data: Any,
|
|
835
|
+
*,
|
|
836
|
+
event_type: str = "unknown",
|
|
837
|
+
platform: str = "unknown",
|
|
838
|
+
) -> asyncio.Task:
|
|
839
|
+
"""
|
|
840
|
+
{!--< internal-use >!--}
|
|
841
|
+
将事件处理器包装为独立 asyncio.Task 并调度执行
|
|
842
|
+
|
|
843
|
+
处理器在独立 Task 中运行,不会阻塞 adapter.emit() 的后续流程。
|
|
844
|
+
自动捕获处理器异常并记录日志,同时监控处理器执行耗时。
|
|
845
|
+
|
|
846
|
+
:param func: 事件处理器函数
|
|
847
|
+
:param data: 事件数据
|
|
848
|
+
:param event_type: 事件类型(用于日志)
|
|
849
|
+
:param platform: 平台名称(用于日志)
|
|
850
|
+
:return: asyncio.Task
|
|
851
|
+
"""
|
|
852
|
+
import time as _time
|
|
853
|
+
|
|
854
|
+
_func_name = getattr(func, "__qualname__", getattr(func, "__name__", str(func)))
|
|
855
|
+
|
|
856
|
+
async def _safe_run():
|
|
857
|
+
t0 = _time.monotonic()
|
|
858
|
+
try:
|
|
859
|
+
await func(data)
|
|
860
|
+
except asyncio.CancelledError:
|
|
861
|
+
pass
|
|
862
|
+
except Exception as e:
|
|
863
|
+
logger.error(
|
|
864
|
+
f"事件处理器执行错误 [{_func_name}] "
|
|
865
|
+
f"type={event_type} platform={platform}: {e}"
|
|
866
|
+
)
|
|
867
|
+
finally:
|
|
868
|
+
elapsed = _time.monotonic() - t0
|
|
869
|
+
if elapsed > HANDLER_SLOW_THRESHOLD_SECS:
|
|
870
|
+
logger.warning(
|
|
871
|
+
f"事件处理器执行缓慢 [{_func_name}] "
|
|
872
|
+
f"耗时 {elapsed:.2f}s > {HANDLER_SLOW_THRESHOLD_SECS}s "
|
|
873
|
+
f"type={event_type} platform={platform}"
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
try:
|
|
877
|
+
return asyncio.create_task(_safe_run())
|
|
878
|
+
except RuntimeError:
|
|
879
|
+
return asyncio.ensure_future(_safe_run())
|
|
880
|
+
|
|
823
881
|
# ==================== Bot状态管理 ====================
|
|
824
882
|
|
|
825
883
|
def _auto_register_bot(self, platform: str, self_info: dict) -> bool:
|
|
@@ -23,7 +23,7 @@ from .Bases.adapter import BaseAdapter
|
|
|
23
23
|
from .config import config
|
|
24
24
|
from .lifecycle import lifecycle
|
|
25
25
|
from .Bases.manager import ManagerBase
|
|
26
|
-
from .constants import ADAPTER_RETRY_BACKOFF_INTERVALS, ADAPTER_RETRY_FIXED_DELAY_SECS, CONFIG_KEY_ADAPTER_STATUS, CONFIG_KEY_ADAPTER_STATUS_OF, DEFAULT_ADAPTER_ENABLED
|
|
26
|
+
from .constants import ADAPTER_RETRY_BACKOFF_INTERVALS, ADAPTER_RETRY_FIXED_DELAY_SECS, CONFIG_KEY_ADAPTER_STATUS, CONFIG_KEY_ADAPTER_STATUS_OF, DEFAULT_ADAPTER_ENABLED, HANDLER_SLOW_THRESHOLD_SECS
|
|
27
27
|
|
|
28
28
|
class AdapterManager(ManagerBase):
|
|
29
29
|
"""
|
|
@@ -218,6 +218,9 @@ class AdapterManager(ManagerBase):
|
|
|
218
218
|
"""
|
|
219
219
|
提交OneBot12协议事件到指定平台
|
|
220
220
|
|
|
221
|
+
每个事件处理器(handler)都在独立的 asyncio.Task 中执行,
|
|
222
|
+
单个处理器阻塞不会影响框架的事件分发和其他处理器运行。
|
|
223
|
+
|
|
221
224
|
:param data: 符合OneBot12标准的事件数据
|
|
222
225
|
|
|
223
226
|
:example:
|
|
@@ -308,6 +308,11 @@ DEFAULT_WAIT_TIMEOUT_SECS = 60.0
|
|
|
308
308
|
# 修改影响: 验证器拒绝回复后的重试次数。
|
|
309
309
|
DEFAULT_MAX_RETRIES = 3
|
|
310
310
|
|
|
311
|
+
# 事件处理器执行耗时警告阈值(秒)。
|
|
312
|
+
# 使用位置: Core/adapter.py -> emit() 中的 handler 执行监控。
|
|
313
|
+
# 修改影响: 当单个处理器执行超过此时间时记录 WARNING 日志。
|
|
314
|
+
HANDLER_SLOW_THRESHOLD_SECS = 1.0
|
|
315
|
+
|
|
311
316
|
# 平台标识的回退值。
|
|
312
317
|
# 当事件数据缺少 platform 字段时使用。
|
|
313
318
|
# 修改影响: 日志和事件处理中的平台标识显示。
|
|
@@ -13,7 +13,7 @@ ErisPulse 生命周期管理模块
|
|
|
13
13
|
|
|
14
14
|
import asyncio
|
|
15
15
|
import inspect
|
|
16
|
-
from .constants import DEFAULT_EVENT_SOURCE
|
|
16
|
+
from .constants import DEFAULT_EVENT_SOURCE, HANDLER_SLOW_THRESHOLD_SECS
|
|
17
17
|
import time
|
|
18
18
|
from typing import Any
|
|
19
19
|
from collections.abc import Callable
|
|
@@ -307,12 +307,18 @@ class LifecycleManager:
|
|
|
307
307
|
:param data: Any 事件数据
|
|
308
308
|
:return: Any 处理后的数据
|
|
309
309
|
"""
|
|
310
|
-
|
|
310
|
+
import time as _time
|
|
311
|
+
for priority, handler in self._hooks[hook_name]:
|
|
311
312
|
try:
|
|
313
|
+
_t = _time.monotonic()
|
|
314
|
+
_hname = getattr(handler, "__qualname__", getattr(handler, "__name__", str(handler)))
|
|
312
315
|
if inspect.iscoroutinefunction(handler):
|
|
313
316
|
result = await handler(data)
|
|
314
317
|
else:
|
|
315
318
|
result = handler(data)
|
|
319
|
+
_elapsed = _time.monotonic() - _t
|
|
320
|
+
if _elapsed > HANDLER_SLOW_THRESHOLD_SECS:
|
|
321
|
+
_get_logger().warning(f"[Lifecycle] Slow handler {_hname} for event '{event}' took {_elapsed:.4f}s")
|
|
316
322
|
if result is not None:
|
|
317
323
|
data = result
|
|
318
324
|
except Exception as e:
|
|
@@ -19,7 +19,7 @@ ErisPulse 生命周期管理模块
|
|
|
19
19
|
|
|
20
20
|
import asyncio
|
|
21
21
|
import inspect
|
|
22
|
-
from .constants import DEFAULT_EVENT_SOURCE
|
|
22
|
+
from .constants import DEFAULT_EVENT_SOURCE, HANDLER_SLOW_THRESHOLD_SECS
|
|
23
23
|
import time
|
|
24
24
|
from typing import Any
|
|
25
25
|
from collections.abc import Callable
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|