本次提交包含多项代码优化与规范修正: 1. 文档与注释优化:修正注释术语、补充注解与FR编号 2. 代码格式调整:统一空格、换行与缩进规范 3. 类型与接口完善:补充__all__导出、修正返回类型注解 4. 错误处理增强:新增领域错误类与校验逻辑 5. 依赖与导入调整:修复路径引用、统一时区导入 6. 协议与契约更新:完善接口文档与一致性注解
188 lines
7.3 KiB
Python
188 lines
7.3 KiB
Python
"""生命周期钩子协议。
|
||
|
||
定义插件生命周期状态枚举、生命周期钩子枚举与生命周期钩子处理 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)。
|
||
FAIL: 失败回调钩子(failed 阶段)。特殊性:非主动状态变迁,
|
||
由宿主在初始化 / 启动 / 运行时失败后调用(FR-32),触发
|
||
FR-36 优雅降级。``onFail`` 自身失败不得阻断降级流程。
|
||
|
||
文件级状态无钩子(FR-PLG-INSTALL):
|
||
``NOT_INSTALLED`` 与 ``INSTALLED`` 为文件级生命周期状态,由
|
||
``PLG-INSTALL`` 端点驱动转换,**不触发** ``LifecycleHook``。
|
||
运行时生命周期从 ``LOADED`` 开始,由宿主状态机驱动并通过本枚举
|
||
对应的钩子通知插件。
|
||
"""
|
||
|
||
INIT = "init"
|
||
START = "start"
|
||
STOP = "stop"
|
||
PAUSE = "pause"
|
||
RESUME = "resume"
|
||
UNLOAD = "unload"
|
||
RECONFIGURE = "reconfigure"
|
||
FAIL = "fail"
|
||
|
||
|
||
@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,超时后标记插件失败。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 INITIALIZED。
|
||
@idempotent: False — 初始化可能涉及资源分配与订阅建立,重复执行有副作用。
|
||
"""
|
||
...
|
||
|
||
async def onStart(self) -> None:
|
||
"""启动钩子,在 started 阶段调用。
|
||
|
||
超时 60s,超时后标记插件失败。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 STARTED。
|
||
@idempotent: False — 启动涉及连接建立与事件订阅,重复执行有副作用。
|
||
"""
|
||
...
|
||
|
||
async def onStop(self) -> None:
|
||
"""停止钩子,在 stopped 阶段调用。
|
||
|
||
超时 30s,必须等待在途请求完成。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 STOPPED。
|
||
@idempotent: True — 停止已停止的插件应安全,重复调用仅产生等价的已停止状态。
|
||
"""
|
||
...
|
||
|
||
async def onPause(self) -> None:
|
||
"""暂停钩子,在 paused 阶段调用。
|
||
|
||
超时 30s。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 PAUSED。
|
||
@idempotent: True — 暂停已暂停的插件应安全,重复调用仅产生等价的已暂停状态。
|
||
"""
|
||
...
|
||
|
||
async def onResume(self) -> None:
|
||
"""恢复钩子,从 paused 恢复到 started。
|
||
|
||
超时 30s。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 STARTED。
|
||
@idempotent: False — 恢复涉及重新激活订阅与连接,重复执行有副作用。
|
||
"""
|
||
...
|
||
|
||
async def onUnload(self) -> None:
|
||
"""卸载钩子,在 unloaded 阶段调用。
|
||
|
||
超时 30s,必须释放所有资源,不得留下孤儿资源。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 UNLOADED。
|
||
@idempotent: True — 卸载已卸载的插件应安全,重复调用仅清理已释放的资源。
|
||
"""
|
||
...
|
||
|
||
async def onReconfigure(self, config: dict[str, Any]) -> None:
|
||
"""配置热更新钩子(FR-37)。
|
||
|
||
参数:
|
||
config: 新配置字典,必须支持回滚。
|
||
|
||
@consistency: 状态机驱动(state-machine),配置变更即时生效且必须支持回滚。
|
||
@idempotent: True — 相同配置字典重复应用应产生等价结果,无累积副作用。
|
||
"""
|
||
...
|
||
|
||
async def onFail(self, error: str) -> None:
|
||
"""插件失败钩子(FR-32)。
|
||
|
||
插件初始化/启动/运行时失败时调用,用于清理资源、记录状态。
|
||
宿主调用此钩子后标记插件为 ``FAILED`` 状态并触发 FR-36 优雅降级。
|
||
|
||
参数:
|
||
error: 错误描述。
|
||
|
||
@consistency: 状态机驱动(state-machine),钩子完成后状态机推进至 FAILED 并触发降级;钩子自身失败不得阻断降级流程。
|
||
@idempotent: True — 重复通知失败应安全,仅记录状态与清理资源,无累积副作用。
|
||
"""
|
||
...
|