ForcePilot/backend/package/yuxi/channels/contract/plugin/lifecycle.py

203 lines
8.2 KiB
Python
Raw Normal View History

"""生命周期钩子协议。
定义插件生命周期状态枚举生命周期钩子枚举与生命周期钩子处理 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,
*,
old_config: dict[str, Any] | None = None,
new_config: dict[str, Any],
) -> None:
"""配置热更新钩子FR-37
参数
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`` 形参
@consistency: 状态机驱动state-machine配置变更即时生效且必须支持回滚
@idempotent: True 相同配置字典重复应用应产生等价结果无累积副作用
"""
...
async def onFail(self, error: str) -> None:
"""插件失败钩子FR-32
插件初始化/启动/运行时失败时调用用于清理资源记录状态
宿主调用此钩子后标记插件为 ``FAILED`` 状态并触发 FR-36 优雅降级
参数
error: 错误描述
@consistency: 状态机驱动state-machine钩子完成后状态机推进至 FAILED 并触发降级钩子失败不阻断降级
@idempotent: True 重复通知失败应安全仅记录状态与清理资源无累积副作用
"""
...