百积木文档
开发指南Bundle 开发高级开发

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。统一协议由 operationTypestage 两个维度组成:

操作类型

  • INSTALL
  • UPGRADE
  • UNINSTALL
  • CONFIG_UPDATE
  • START
  • STOP

执行阶段

阶段职责
PREPARE校验前置条件、解析资源差异并生成外部执行计划
APPLY创建、更新、停用或回收外部资源
VERIFY验证外部状态是否已经达到目标版本
COMMIT固化执行结果和外部资源绑定
ROLLBACK回滚尚未提交且能够原子撤销的动作
COMPENSATE对无法原子回滚的动作执行反向补偿
STATUS查询异步操作状态,用于恢复中断的安装任务

例如,一次正常安装依次执行:

INSTALL × PREPARE
  -> INSTALL × APPLY
  -> Bundle 资源物化
  -> INSTALL × VERIFY
  -> INSTALL × COMMIT

失败时,Bundle Service 根据已经持久化的检查点,按逆序调用 ROLLBACKCOMPENSATE。插件不能自己推进 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": {}
}

workspaceIdapplicationRuntimeIdbundleInstallId 和资源身份必须来自平台可信 上下文,不能信任页面或普通业务参数传入的同名字段。

响应和输出

插件响应至少需要表达:

  • READYRUNNINGSUCCEEDEDFAILEDNEEDS_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 不应直接成为外部 业务主键:

标识用途
bundleInstallIdBundle 安装实例的稳定平台身份
applicationRuntimeId安装所在 Runtime
externalInstanceId插件生成的外部安装实例主键
vendorTenantId用户已有的第三方租户编号,可由用户填写

一个 Bundle 在不同 Runtime 安装时,插件应创建或绑定相互隔离的安装实例。同一个安装 重试时必须通过幂等键返回原结果,不能重复创建租户。Bundle 内同一个模块在同一个 Runtime 仍然只能安装一次。

多个模块可以共享同一个 externalInstanceId,因为外部实例属于 Bundle 安装,而不是 其中某一个模块。

验证清单

  1. 不带插件的普通 Bundle 可以完整安装、升级和卸载。
  2. 插件注册失败和 Bundle 绑定失败是两类独立错误。
  3. 同一次操作重试不会重复创建外部资源。
  4. 两个 Runtime 的安装不会共享凭据或错误覆盖外部实例。
  5. 插件输出只能写入 Bundle 声明允许修改的资源属性。
  6. PREPAREAPPLYVERIFYCOMMIT 都有持久化记录。
  7. 中断后可以通过 STATUS 和检查点恢复。
  8. 失败时执行正确的 ROLLBACKCOMPENSATE,并保留可审计结果。
  9. 升级保持正确的外部安装身份,卸载不会影响其他 Runtime。
  10. 插件不可用时 Bundle 操作明确失败,不能静默跳过。

本页内容