2026-07-02 03:22:12 +08:00
|
|
|
|
"""生命周期钩子协议。
|
|
|
|
|
|
|
|
|
|
|
|
定义插件生命周期状态枚举、生命周期钩子枚举与生命周期钩子处理 Protocol。
|
|
|
|
|
|
插件通过实现 ``LifecycleHookHandler`` 响应宿主下发的状态变迁,宿主在调用
|
|
|
|
|
|
钩子时施加超时控制并在失败时触发优雅降级。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from enum import StrEnum
|
|
|
|
|
|
from typing import Any, Protocol, runtime_checkable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LifecycleState(StrEnum):
|
|
|
|
|
|
"""生命周期状态。
|
|
|
|
|
|
|
|
|
|
|
|
标识插件在生命周期中的当前状态,由宿主状态机驱动变迁。继承
|
|
|
|
|
|
``str, Enum`` 以支持 JSON 序列化与字符串比较。
|
|
|
|
|
|
|
|
|
|
|
|
取值:
|
|
|
|
|
|
DISCOVERED: 已发现(清单已加载)。
|
|
|
|
|
|
RESOLVED: 已解析(依赖已满足)。
|
|
|
|
|
|
LOADED: 已加载(模块已导入)。
|
|
|
|
|
|
INITIALIZED: 已初始化(onInit 完成)。
|
|
|
|
|
|
STARTED: 已启动(onStart 完成)。
|
|
|
|
|
|
PAUSED: 已暂停(onPause 完成)。
|
|
|
|
|
|
STOPPED: 已停止(onStop 完成)。
|
|
|
|
|
|
UNLOADED: 已卸载(onUnload 完成,资源已释放)。
|
|
|
|
|
|
FAILED: 失败(onFail 已调用,触发优雅降级)。
|
|
|
|
|
|
NOT_INSTALLED: 未安装(文件级生命周期初始态,插件文件不存在)。
|
|
|
|
|
|
INSTALLED: 已安装(插件文件已放置到插件目录,manifest 已注册,
|
|
|
|
|
|
尚未 load 进入运行时生命周期)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
DISCOVERED = "discovered"
|
|
|
|
|
|
RESOLVED = "resolved"
|
|
|
|
|
|
LOADED = "loaded"
|
|
|
|
|
|
INITIALIZED = "initialized"
|
|
|
|
|
|
STARTED = "started"
|
|
|
|
|
|
PAUSED = "paused"
|
|
|
|
|
|
STOPPED = "stopped"
|
|
|
|
|
|
UNLOADED = "unloaded"
|
|
|
|
|
|
FAILED = "failed"
|
|
|
|
|
|
NOT_INSTALLED = "not_installed"
|
|
|
|
|
|
INSTALLED = "installed"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LifecycleHook(StrEnum):
|
|
|
|
|
|
"""生命周期钩子。
|
|
|
|
|
|
|
|
|
|
|
|
标识宿主可调用的生命周期钩子类型,与 ``LifecycleHookHandler`` 方法
|
|
|
|
|
|
一一对应。继承 ``str, Enum`` 以支持 JSON 序列化与字符串比较。
|
|
|
|
|
|
|
|
|
|
|
|
取值:
|
|
|
|
|
|
INIT: 初始化钩子(initialized 阶段)。
|
|
|
|
|
|
START: 启动钩子(started 阶段)。
|
|
|
|
|
|
STOP: 停止钩子(stopped 阶段)。
|
|
|
|
|
|
PAUSE: 暂停钩子(paused 阶段)。
|
|
|
|
|
|
RESUME: 恢复钩子(从 paused 恢复至 started)。
|
|
|
|
|
|
UNLOAD: 卸载钩子(unloaded 阶段)。
|
|
|
|
|
|
RECONFIGURE: 配置热更新钩子(FR-37)。
|
2026-07-02 18:27:06 +08:00
|
|
|
|
FAIL: 失败回调钩子(failed 阶段)。特殊性:非主动状态变迁,
|
|
|
|
|
|
由宿主在初始化 / 启动 / 运行时失败后调用(FR-32),触发
|
|
|
|
|
|
FR-36 优雅降级。``onFail`` 自身失败不得阻断降级流程。
|
|
|
|
|
|
|
|
|
|
|
|
文件级状态无钩子(FR-PLG-INSTALL):
|
|
|
|
|
|
``NOT_INSTALLED`` 与 ``INSTALLED`` 为文件级生命周期状态,由
|
|
|
|
|
|
``PLG-INSTALL`` 端点驱动转换,**不触发** ``LifecycleHook``。
|
|
|
|
|
|
运行时生命周期从 ``LOADED`` 开始,由宿主状态机驱动并通过本枚举
|
|
|
|
|
|
对应的钩子通知插件。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
INIT = "init"
|
|
|
|
|
|
START = "start"
|
|
|
|
|
|
STOP = "stop"
|
|
|
|
|
|
PAUSE = "pause"
|
|
|
|
|
|
RESUME = "resume"
|
|
|
|
|
|
UNLOAD = "unload"
|
|
|
|
|
|
RECONFIGURE = "reconfigure"
|
2026-07-02 18:27:06 +08:00
|
|
|
|
FAIL = "fail"
|
2026-07-02 03:22:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@runtime_checkable
|
|
|
|
|
|
class LifecycleHookHandler(Protocol):
|
|
|
|
|
|
"""生命周期钩子处理 Protocol。
|
|
|
|
|
|
|
|
|
|
|
|
由插件实现,响应宿主下发的生命周期状态变迁。使用
|
|
|
|
|
|
``@runtime_checkable`` 装饰以支持 ``isinstance`` 检查。所有钩子
|
|
|
|
|
|
均为异步方法,宿主在调用时施加超时控制。
|
|
|
|
|
|
|
|
|
|
|
|
超时配置(FR-32):
|
|
|
|
|
|
- ``onInit`` / ``onStart``:默认 60s。
|
|
|
|
|
|
- ``onPause`` / ``onResume`` / ``onStop`` / ``onUnload``:默认 30s。
|
|
|
|
|
|
- 超时后宿主标记插件为 ``FAILED`` 状态并触发 FR-36 优雅降级。
|
|
|
|
|
|
|
|
|
|
|
|
资源释放约束(FR-32):
|
|
|
|
|
|
- 插件卸载时(``onUnload``)**必须** 释放所有资源(关闭连接、
|
|
|
|
|
|
清理缓存、取消订阅),**不得** 留下孤儿资源。
|
|
|
|
|
|
- 插件停止时(``onStop``)**必须** 等待在途请求完成(默认超时
|
|
|
|
|
|
30s),超时后强制中止并记录告警日志。
|
|
|
|
|
|
- ``onReconfigure`` 用于配置热更新(FR-37),**必须** 支持配置回滚。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
async def onInit(self) -> None:
|
|
|
|
|
|
"""初始化钩子,在 initialized 阶段调用。
|
|
|
|
|
|
|
|
|
|
|
|
超时 60s,超时后标记插件失败。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 INITIALIZED。
|
|
|
|
|
|
@idempotent: False — 初始化可能涉及资源分配与订阅建立,重复执行有副作用。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
async def onStart(self) -> None:
|
|
|
|
|
|
"""启动钩子,在 started 阶段调用。
|
|
|
|
|
|
|
|
|
|
|
|
超时 60s,超时后标记插件失败。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 STARTED。
|
|
|
|
|
|
@idempotent: False — 启动涉及连接建立与事件订阅,重复执行有副作用。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
async def onStop(self) -> None:
|
|
|
|
|
|
"""停止钩子,在 stopped 阶段调用。
|
|
|
|
|
|
|
|
|
|
|
|
超时 30s,必须等待在途请求完成。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 STOPPED。
|
|
|
|
|
|
@idempotent: True — 停止已停止的插件应安全,重复调用仅产生等价的已停止状态。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
async def onPause(self) -> None:
|
|
|
|
|
|
"""暂停钩子,在 paused 阶段调用。
|
|
|
|
|
|
|
|
|
|
|
|
超时 30s。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 PAUSED。
|
|
|
|
|
|
@idempotent: True — 暂停已暂停的插件应安全,重复调用仅产生等价的已暂停状态。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
async def onResume(self) -> None:
|
|
|
|
|
|
"""恢复钩子,从 paused 恢复到 started。
|
|
|
|
|
|
|
|
|
|
|
|
超时 30s。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 STARTED。
|
|
|
|
|
|
@idempotent: False — 恢复涉及重新激活订阅与连接,重复执行有副作用。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
async def onUnload(self) -> None:
|
|
|
|
|
|
"""卸载钩子,在 unloaded 阶段调用。
|
|
|
|
|
|
|
|
|
|
|
|
超时 30s,必须释放所有资源,不得留下孤儿资源。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 UNLOADED。
|
|
|
|
|
|
@idempotent: True — 卸载已卸载的插件应安全,重复调用仅清理已释放的资源。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
2026-07-06 20:49:35 +08:00
|
|
|
|
async def onReconfigure(
|
|
|
|
|
|
self,
|
|
|
|
|
|
*,
|
|
|
|
|
|
old_config: dict[str, Any] | None = None,
|
|
|
|
|
|
new_config: dict[str, Any],
|
|
|
|
|
|
) -> None:
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""配置热更新钩子(FR-37)。
|
|
|
|
|
|
|
|
|
|
|
|
参数:
|
2026-07-06 20:49:35 +08:00
|
|
|
|
old_config: 上一次的有效配置字典,由宿主在调用时通过关键字参数
|
|
|
|
|
|
传入;首次调用或无基线时为 ``None``。插件可据此做差异化校验,
|
|
|
|
|
|
无需自行维护基线缓存。
|
|
|
|
|
|
new_config: 新配置字典,必须支持回滚。
|
|
|
|
|
|
|
|
|
|
|
|
迁移说明:本 Protocol 声明 ``old_config`` 形参。旧插件升级时应补充
|
|
|
|
|
|
``old_config`` 形参以接收旧配置;若旧插件实现
|
|
|
|
|
|
``async def onReconfigure(self, *, new_config)``(无 ``old_config``),
|
|
|
|
|
|
宿主调用时传 ``old_config=...`` 会触发 ``TypeError``。宿主实现侧如需
|
|
|
|
|
|
兼容此类旧插件,可通过 ``inspect`` 检查方法签名决定是否传 ``old_config``
|
|
|
|
|
|
(如 ``inspect.signature`` 检测是否含 ``old_config`` 形参)。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
|
|
|
|
|
@consistency: 状态机驱动(state-machine),配置变更即时生效且必须支持回滚。
|
|
|
|
|
|
@idempotent: True — 相同配置字典重复应用应产生等价结果,无累积副作用。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
async def onFail(self, error: str) -> None:
|
|
|
|
|
|
"""插件失败钩子(FR-32)。
|
|
|
|
|
|
|
|
|
|
|
|
插件初始化/启动/运行时失败时调用,用于清理资源、记录状态。
|
|
|
|
|
|
宿主调用此钩子后标记插件为 ``FAILED`` 状态并触发 FR-36 优雅降级。
|
|
|
|
|
|
|
|
|
|
|
|
参数:
|
|
|
|
|
|
error: 错误描述。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
|
2026-07-04 00:14:56 +08:00
|
|
|
|
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 FAILED 并触发降级;钩子失败不阻断降级。
|
2026-07-03 19:18:13 +08:00
|
|
|
|
@idempotent: True — 重复通知失败应安全,仅记录状态与清理资源,无累积副作用。
|
2026-07-02 03:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
|
...
|