Bundle 生命周期插件
注册外部插件服务,并把它接入整个 Bundle 的安装、升级、验证、提交和补偿流程。
Bundle 生命周期插件是高级安装扩展。它处理整个 Bundle 的外部资源生命周期;模块只是 Bundle 中的一类资源,不单独拥有插件。
能力状态
Bundle 顶层生命周期插件协议正在标准化。使用前必须确认当前 Bundle Service 和
Lifecycle Plugin Manager 已支持对应 protocolVersion。当前版本未开放的 Manifest
字段不能仅根据本文示例写入生产 Bundle。历史模块级 external-managed 只用于兼容
已有模块,不能替代完整的 Bundle 生命周期。
注册、绑定和安装是三套状态
| 状态 | 负责人 | 内容 |
|---|---|---|
| 插件服务注册 | 插件提供方和插件注册服务 | 服务身份、协议版本、Endpoint、鉴权和支持的方法 |
| Bundle 插件绑定 | Bundle 作者和 Bundle Service | 引用哪个注册插件、执行顺序、失败策略和非敏感配置 |
| 插件执行实例 | Bundle Service 和 Lifecycle Plugin Manager | 某次安装操作的阶段、检查点、结果、重试和补偿记录 |
插件提供方先独立注册服务;Bundle 作者引用注册记录;最终用户安装 Bundle 时不需要再次 注册插件。安装用户只填写该 Bundle 明确公开的安装参数。
插件体系的管理与执行能力
插件注册仍然是单独一套逻辑,不并入 Bundle 定义:
- 插件注册服务负责注册、查询、更新和停用插件服务。
- 注册记录声明服务身份、协议版本、Endpoint、鉴权方式和支持的操作类型。
- Bundle 只引用注册标识,不复制注册数据,也不要求安装用户重新注册。
生命周期插件管理器负责执行侧能力:
- 在 Bundle 冻结时解析注册记录并锁定插件 revision。
- 校验 Bundle 绑定、执行顺序、失败策略和输出范围。
- 执行生命周期阶段并持久化请求、响应和检查点。
- 查询异步状态,执行受控重试、回滚和补偿。
- 按 Bundle 安装、Runtime、操作和插件查询审计记录。
Bundle Service 决定何时推进安装状态;生命周期插件管理器负责可靠分发和执行插件调用; 插件注册服务提供独立的服务目录。三者不能各自维护一套相互冲突的 Bundle 生命周期状态。
生命周期协议
不要为模块动作不断增加零散 Hook。统一协议由 operationType 和 stage 两个维度组成:
操作类型
INSTALLUPGRADEUNINSTALLCONFIG_UPDATESTARTSTOP
执行阶段
| 阶段 | 职责 |
|---|---|
PREPARE | 校验前置条件、解析资源差异并生成外部执行计划 |
APPLY | 创建、更新、停用或回收外部资源 |
VERIFY | 验证外部状态是否已经达到目标版本 |
COMMIT | 固化执行结果和外部资源绑定 |
ROLLBACK | 回滚尚未提交且能够原子撤销的动作 |
COMPENSATE | 对无法原子回滚的动作执行反向补偿 |
STATUS | 查询异步操作状态,用于恢复中断的安装任务 |
例如,一次正常安装依次执行:
INSTALL × PREPARE
-> INSTALL × APPLY
-> Bundle 资源物化
-> INSTALL × VERIFY
-> INSTALL × COMMIT失败时,Bundle Service 根据已经持久化的检查点,按逆序调用 ROLLBACK 或
COMPENSATE。插件不能自己推进 Bundle 安装状态。
请求上下文
每次调用都必须带稳定操作标识、幂等键、Bundle 安装身份和完整资源差异。概念结构如下:
{
"operationId": "op-8f6d",
"idempotencyKey": "install-300:INSTALL:APPLY:tenant-provider",
"operationType": "INSTALL",
"stage": "APPLY",
"workspaceId": 100,
"applicationRuntimeId": 200,
"bundleInstallId": 300,
"bundle": {
"bundleId": "crm-suite",
"fromVersion": null,
"targetVersion": "1.3.0",
"resolvedLockDigest": "sha256:..."
},
"resourceDiff": {
"added": [],
"changed": [],
"removed": []
},
"configuration": {}
}workspaceId、applicationRuntimeId、bundleInstallId 和资源身份必须来自平台可信
上下文,不能信任页面或普通业务参数传入的同名字段。
响应和输出
插件响应至少需要表达:
READY、RUNNING、SUCCEEDED、FAILED或NEEDS_ATTENTION状态。- 可恢复的
checkpoint或异步任务标识。 - 允许 Bundle Service 应用的资源配置输出。
- 警告、结构化错误和建议重试时间。
- 已创建或复用的外部资源引用。
插件可以返回外部租户编号、许可证引用或数据库 Allocation 引用,但不能直接修改模块 安装记录。Bundle Service 负责校验输出允许写入哪些资源属性,并把结果纳入操作台账。
Bundle 声明
目标模型中,生命周期插件位于 Bundle 顶层,而不是 modules[].plugins:
{
"lifecyclePlugins": [
{
"pluginId": "crm-provisioner",
"serviceId": 10,
"protocolVersion": "bundle-lifecycle/v1",
"order": 100,
"failurePolicy": "FAIL_FAST",
"configuration": {}
}
],
"backendModules": [],
"platformApplications": []
}这是协议模型示例,不代表所有当前环境已经接受该字段。Bundle 冻结时应锁定插件注册
记录、协议版本、插件 revision、执行顺序、失败策略和配置摘要;真实 Endpoint、访问
token 和数据库凭据不能进入 Manifest 或 resolvedLock。
Runtime 与外部租户
每次 Bundle 安装都需要可追踪地归属于一个 Runtime,但 Runtime ID 不应直接成为外部 业务主键:
| 标识 | 用途 |
|---|---|
bundleInstallId | Bundle 安装实例的稳定平台身份 |
applicationRuntimeId | 安装所在 Runtime |
externalInstanceId | 插件生成的外部安装实例主键 |
vendorTenantId | 用户已有的第三方租户编号,可由用户填写 |
一个 Bundle 在不同 Runtime 安装时,插件应创建或绑定相互隔离的安装实例。同一个安装 重试时必须通过幂等键返回原结果,不能重复创建租户。Bundle 内同一个模块在同一个 Runtime 仍然只能安装一次。
多个模块可以共享同一个 externalInstanceId,因为外部实例属于 Bundle 安装,而不是
其中某一个模块。
验证清单
- 不带插件的普通 Bundle 可以完整安装、升级和卸载。
- 插件注册失败和 Bundle 绑定失败是两类独立错误。
- 同一次操作重试不会重复创建外部资源。
- 两个 Runtime 的安装不会共享凭据或错误覆盖外部实例。
- 插件输出只能写入 Bundle 声明允许修改的资源属性。
PREPARE、APPLY、VERIFY和COMMIT都有持久化记录。- 中断后可以通过
STATUS和检查点恢复。 - 失败时执行正确的
ROLLBACK或COMPENSATE,并保留可审计结果。 - 升级保持正确的外部安装身份,卸载不会影响其他 Runtime。
- 插件不可用时 Bundle 操作明确失败,不能静默跳过。