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.
Files changed (130) hide show
  1. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/PKG-INFO +1 -1
  2. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/pyproject.toml +1 -1
  3. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/base.py +7 -1
  4. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/base.pyi +2 -1
  5. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/command.py +1 -0
  6. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/adapter.py +66 -8
  7. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/adapter.pyi +4 -1
  8. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/constants.py +5 -0
  9. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/lifecycle.py +8 -2
  10. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/lifecycle.pyi +1 -1
  11. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/.gitignore +0 -0
  12. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/LICENSE +0 -0
  13. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/README.md +0 -0
  14. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/__init__.py +0 -0
  15. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/__init__.pyi +0 -0
  16. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/base.py +0 -0
  17. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/base.pyi +0 -0
  18. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/cli.py +0 -0
  19. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/cli.pyi +0 -0
  20. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/__init__.py +0 -0
  21. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/__init__.pyi +0 -0
  22. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/create.py +0 -0
  23. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/create.pyi +0 -0
  24. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/init.py +0 -0
  25. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/init.pyi +0 -0
  26. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/install.py +0 -0
  27. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/install.pyi +0 -0
  28. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list.py +0 -0
  29. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list.pyi +0 -0
  30. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
  31. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/list_remote.pyi +0 -0
  32. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/run.py +0 -0
  33. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/run.pyi +0 -0
  34. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/self_update.py +0 -0
  35. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/self_update.pyi +0 -0
  36. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
  37. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/uninstall.pyi +0 -0
  38. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
  39. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/commands/upgrade.pyi +0 -0
  40. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/console.py +0 -0
  41. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/console.pyi +0 -0
  42. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/registry.py +0 -0
  43. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/registry.pyi +0 -0
  44. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/__init__.py +0 -0
  45. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/__init__.pyi +0 -0
  46. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/display.py +0 -0
  47. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/display.pyi +0 -0
  48. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
  49. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/CLI/utils/package_manager.pyi +0 -0
  50. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/__init__.py +0 -0
  51. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/__init__.pyi +0 -0
  52. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/adapter.py +0 -0
  53. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/adapter.pyi +0 -0
  54. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/manager.py +0 -0
  55. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/manager.pyi +0 -0
  56. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/module.py +0 -0
  57. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/module.pyi +0 -0
  58. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/storage.py +0 -0
  59. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Bases/storage.pyi +0 -0
  60. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/__init__.py +0 -0
  61. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/__init__.pyi +0 -0
  62. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/command.pyi +0 -0
  63. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message.py +0 -0
  64. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message.pyi +0 -0
  65. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message_builder.py +0 -0
  66. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/message_builder.pyi +0 -0
  67. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/meta.py +0 -0
  68. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/meta.pyi +0 -0
  69. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/notice.py +0 -0
  70. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/notice.pyi +0 -0
  71. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/request.py +0 -0
  72. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/request.pyi +0 -0
  73. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/session_type.py +0 -0
  74. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/session_type.pyi +0 -0
  75. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/wrapper.py +0 -0
  76. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/Event/wrapper.pyi +0 -0
  77. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/__init__.py +0 -0
  78. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/__init__.pyi +0 -0
  79. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/config.py +0 -0
  80. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/config.pyi +0 -0
  81. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/constants.pyi +0 -0
  82. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/logger.py +0 -0
  83. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/logger.pyi +0 -0
  84. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/module.py +0 -0
  85. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/module.pyi +0 -0
  86. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/router.py +0 -0
  87. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/router.pyi +0 -0
  88. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/storage.py +0 -0
  89. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/Core/storage.pyi +0 -0
  90. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__init__.py +0 -0
  91. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__init__.pyi +0 -0
  92. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__main__.py +0 -0
  93. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/__main__.pyi +0 -0
  94. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/__init__.py +0 -0
  95. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/__init__.pyi +0 -0
  96. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/adapter.py +0 -0
  97. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/adapter.pyi +0 -0
  98. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/__init__.py +0 -0
  99. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/__init__.pyi +0 -0
  100. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/finder.py +0 -0
  101. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/bases/finder.pyi +0 -0
  102. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/module.py +0 -0
  103. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/finders/module.pyi +0 -0
  104. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/__init__.py +0 -0
  105. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/__init__.pyi +0 -0
  106. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/adapter.py +0 -0
  107. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/adapter.pyi +0 -0
  108. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/__init__.py +0 -0
  109. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/__init__.pyi +0 -0
  110. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/loader.py +0 -0
  111. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/bases/loader.pyi +0 -0
  112. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/module.py +0 -0
  113. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/module.pyi +0 -0
  114. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/strategy.py +0 -0
  115. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/loaders/strategy.pyi +0 -0
  116. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/__init__.py +0 -0
  117. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/__init__.pyi +0 -0
  118. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/context.py +0 -0
  119. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/context.pyi +0 -0
  120. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/exceptions.py +0 -0
  121. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/exceptions.pyi +0 -0
  122. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/frame_config.py +0 -0
  123. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/runtime/frame_config.pyi +0 -0
  124. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/sdk.py +0 -0
  125. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/sdk.pyi +0 -0
  126. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/4xx.png +0 -0
  127. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/5xx.png +0 -0
  128. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/__init__.py +0 -0
  129. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/__init__.pyi +0 -0
  130. {erispulse-2.4.6.dev2 → erispulse-2.4.6.dev3}/src/ErisPulse/web_status/unknow.png +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 2.4.6.dev2
3
+ Version: 2.4.6.dev3
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: ErisDev <erisdev@88.com>
6
6
  Maintainer-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ErisPulse"
7
- version = "2.4.6-dev.2"
7
+ version = "2.4.6-dev.3"
8
8
  description = "ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -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
@@ -286,6 +286,7 @@ class CommandHandler:
286
286
  # 清理超时的等待
287
287
  if wait_key in self._waiting_replies:
288
288
  del self._waiting_replies[wait_key]
289
+ logger.debug(f"wait_reply 超时: key={wait_key}, timeout={timeout}s")
289
290
  return None
290
291
  except Exception as e:
291
292
  # 清理异常情况
@@ -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
- await handler_wrapper["func"](processed_data)
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
- await handler_wrapper["func"](platform_raw)
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
- for _, handler in self._hooks[hook_name]:
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