简体中文 English 繁體中文 日本語 Русский
本文为静态镜像,内容以交互版为准 在交互式文档中心打开 →

ErisPulse.Core.lifecycle 模块


模块概述

ErisPulse 生命周期管理模块

提供统一的钩子/事件管理和触发机制,支持点式结构事件监听与定向传播

提示

  1. 使用 @lifecycle.on("event.name") 注册事件处理器
  2. 使用 await lifecycle.emit("event.name", data) 触发事件
  3. 使用 lifecycle.emit("event.name", data, to="Owner") 定向投递给指定 owner 注册的钩子
  4. 使用 lifecycle.start_timer() / stop_timer() 进行计时
  5. 旧版 submit_event() API 保持兼容

类列表

class LifecycleManager

生命周期管理器

统一的钩子/事件系统,支持:

提示 两种注册方式等价:

@lifecycle.on("module.load") ... async def on_load(data): ... print(data) lifecycle.register("module.load", on_load) 两种触发方式等价: await lifecycle.emit("module.load", {"module_name": "Test"}) await lifecycle.submit_event("module.load", data={"module_name": "Test"})

嵌套类

class _NullLogger

静默日志器,在 logger 模块尚未初始化时作为替代

方法列表

_get_logger()

延迟导入 logger,避免循环依赖(lifecycle → logger → config → lifecycle)


on(event: str)

注册事件处理器(装饰器模式)

异常: ValueError - 当事件名无效时抛出

示例:

>>> @lifecycle.on("module.load")
... async def on_module_load(data):
...     print(f"模块加载: {data}")
>>>
>>> @lifecycle.on("adapter.*")
... def on_adapter_event(data):
...     pass

register(event: str, handler: Callable)

注册事件处理器(函数调用模式)

示例:

>>> lifecycle.register("config.set", my_handler, priority=10)

once(event: str)

注册一次性事件处理器(触发一次后自动注销)

示例:

>>> @lifecycle.once("core.init.complete")
... async def on_first_ready(data):
...     print("首次就绪")

has_handlers(event: str)

检查指定事件是否已有注册的处理器(含通配符 * 与父级事件)

可用于热路径短路:发射事件前先判断有无监听者,避免无谓的字典遍历与任务调度。

示例:

>>> if lifecycle.has_handlers("message.sending"):
...     await lifecycle.emit("message.sending", data)

unregister(event: str, handler: Callable | None = None)

取消注册事件处理器

示例:

>>> lifecycle.unregister("config.set", my_handler)  # 取消指定处理器
>>> lifecycle.unregister("config.set")               # 取消所有处理器

unregister_by_owner(owner: str)

取消指定 owner 注册的所有事件处理器

用于模块/适配器卸载时自动清理其注册的钩子,避免闭包引用导致内存泄漏。

示例:

>>> lifecycle.unregister_by_owner("MyModule")

get_owner_counts()

统计各 owner 注册的生命周期钩子数量(便于拓扑树展示)

返回值 ({owner:): 钩子数量} 字典

示例:

>>> lifecycle.get_owner_counts()
{"MyModule": 3, "onebot11": 2}

_is_shadow_owner(owner: 'str | None')

内部方法 判断 owner 是否为影子模块 owner(方向十一;惰性导入避免加载链耦合)


_is_shadow_module_event(data: Any)

内部方法 判断事件数据是否携带影子模块的 module_name(module.* 生命周期静默用; 兼容 submit_event 包装形态 {"data": {"module_name": ...}} 与扁平形态)


async emit(event: str, data: Any = None)

触发事件(异步)

匹配的处理器并行执行(各自包装为协程经 gather 并发,互不阻塞, 本调用等待全部完成):慢处理器不拖累其余处理器与触发方,但 emit 返回时 所有处理器已执行完毕(顺序敏感的消费者可安全在 emit 之后读状态)。 处理器返回非 None 值时按注册(优先级)顺序回放链式替换 data—— 所有处理器收到的是同一份输入数据。

指定 to 时进入定向传播:事件只分发给以该拥有者(owner)身份注册的 处理器(模块在 on_load 内注册 / owner_scope 上下文注册的钩子), 其它模块与通配符 * 处理器不感知;目标 owner 无已注册钩子时静默丢弃。

示例:

>>> result = await lifecycle.emit("config.set", {"key": "test", "value": 42})
>>> # 定向投递给 Chat 模块注册的钩子
>>> await lifecycle.emit("maintenance", {"action": "reload"}, to="Chat")

emit_sync(event: str, data: Any = None)

触发事件(同步,精简版)

同步执行所有处理器。异步处理器会在当前事件循环中以 create_task 调度。 注意:同步模式下异步处理器的返回值无法回传。

指定 to 时进入定向传播(语义同 :meth:emit 的定向模式)。

示例:

>>> result = lifecycle.emit_sync("config.set", {"key": "test"})

fire(event: str, data: Any = None)

触发事件(后台,扔桶即走)——观测类事件的零成本发射

与 :meth:emit 的差异:处理器在后台任务中并行执行,不等待完成、 无返回值,本调用在无监听者时零开销(has_handlers 短路), 有监听者时仅付出一次任务调度成本。适用于高频热路径与纯观测事件 (如 server.request / storage.ready)。

.. warning:: 后台事件不保证执行时机:emit 返回 ≠ 处理器已执行; 框架关停期间后台任务会被取消——关停序列(uninit)中的 事件请改用 :meth:emit。顺序敏感的消费(如 config.set 驱动的作用域重建)同样必须用 :meth:emit。

示例:

>>> lifecycle.fire("server.request", {"method": "GET", "path": "/"})

async submit_event(event_type: str)

提交生命周期事件(兼容旧版 API)

构建标准事件格式后通过 emit 触发,处理器接收标准事件字典; background=True 时改走 :meth:fire 后台发射(不等待处理器, 适用于进度展示类观测事件,如 core.init.stage)。

异常: ValueError - to 为空字符串时

示例:

>>> await lifecycle.submit_event("module.load", data={"module_name": "Test"})
>>> await lifecycle.submit_event("maintenance", data={"action": "reload"}, to="Chat")

start_timer(timer_id: str)

开始计时


get_duration(timer_id: str)

获取指定计时器的持续时间


stop_timer(timer_id: str)

停止计时并返回持续时间


async _execute_handlers(hook_name: str, event: str, data: Any, owner_filter: str | None = None)

执行匹配事件的处理(异步,处理器并行)

每个处理器包装为独立协程经 asyncio.gather 并行执行——慢处理器 不再阻塞其余处理器与触发方,总耗时从"各处理器之和"降为"最慢一个"。 处理器返回非 None 值时按注册(优先级)顺序回放链式替换 data: 所有处理器收到的是同一份输入,回放顺序确定性可预期。


_execute_handlers_sync(hook_name: str, event: str, data: Any, owner_filter: str | None = None)

执行匹配的事件处理器(同步)


clear()

清除所有已注册的处理器和计时器

示例:

>>> lifecycle.clear()

list_hooks()

列出所有已注册的钩子及其处理器数量

返回值 (dict): 钩子名称到处理器数量的映射

示例:

>>> info = lifecycle.list_hooks()
>>> # {"module.load": 2, "adapter.start": 1}