ForcePilot/backend/package/yuxi/channels/contract/plugin/lifecycle.py
Kris 742299cb07 chore: 批量清理报告相关代码并完成多项功能迭代
本次提交包含多维度代码优化与功能增强:
1.  移除报告模块冗余导入与枚举,清理报表相关代码
2.  新增扫码登录支持方法与飞书适配器适配
3.  完善异常日志与健康检查信息
4.  扩展目录、配对管理、能力查询等接口
5.  优化出站管道与事务提交后钩子逻辑
6.  修复飞书消息解析与响应空值问题
7.  重构配置更新与服务账号创建逻辑
8.  统一传输错误分类契约与错误基类扩展
2026-07-06 20:49:35 +08:00

203 lines
8.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""生命周期钩子协议。
定义插件生命周期状态枚举、生命周期钩子枚举与生命周期钩子处理 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 — 重复通知失败应安全,仅记录状态与清理资源,无累积副作用。
"""
...