百积木文档
开发指南平台应用、模块与 Bundle 开发模块开发

模块事件与发布机制

区分事件声明、发布和订阅,并通过当前 Runtime 安全发布模块事件。

模块事件是安装到 Runtime 的类型化业务能力。事件名和载荷由 Module 版本声明;发布方调用当前 Runtime 物化出的事件方法;订阅、触发和投递由独立资源管理。三者不是同一个动作:

module.json events 声明
  -> 创建不可变 Module 版本并随 Bundle 发布
  -> 安装到目标 Runtime,物化事件方法和发布能力
  -> 工作流或模块后端发布事件
  -> 已安装的 Event Trigger / 订阅消费事件

事件声明、事件发布和事件订阅是三份独立合同。因此,新增 events 不会自动发送事件,也不会自动创建 工作流、Webhook 或 Event Trigger。事件生产方必须 显式发布;需要自动触发后续动作时,还要把相应触发资源纳入 Bundle。

地址从哪里来

事件发布地址不写死,也不由 Bundle 作者填写。Runtime 会根据目标环境和当前安装实例生成可调用的事件方法, 并同时生成作用于该 Runtime 的授权。应用代码和工作流都不能保存或推断内部主机、端口、服务地址、Runtime businessId 或事件平台凭据。

对调用方而言,事件方法与普通 Runtime 方法使用同一调用入口和授权边界;不存在需要开发者选择的“事件 专用网关”或额外协议。地址在环境迁移、重新安装或授权轮换后可以变化,所以必须使用当前 Runtime 物化并 交付的值。

从工作流发布

工作流使用 emit_event 节点。service 必须是 Bundle Manifest 中 Module 资源的完整 Bundle Resource Locator, eventName 必须是该 Module 当前版本声明的事件名,payload 必须符合其 paramDefinitions

{
  "type": "emit_event",
  "id": "emit_order_status_changed",
  "name": "发布订单状态变更",
  "service": "baijimu/example-orders/MODULE/orders",
  "eventName": "orderStatusChanged",
  "payload": {
    "orderId": "{{input.orderId}}",
    "status": "{{context.order.status}}",
    "occurredAt": "{{context.order.occurredAt}}"
  },
  "idempotencyKey": "order-status:{{input.orderId}}:{{context.order.status}}",
  "timeoutSecs": 30
}

安装物化时,平台会用目标 Runtime 中已经验证的 Bundle 安装资源解析 Locator 并生成执行授权。Workflow 定义中不得出现 Runtime businessId、原始 URL 或 Authorization。通用 http 节点不能替代 emit_event:它不提供 Module Locator 解析、事件合同校验和 Runtime 作用域授权。

完整节点字段见工作流Workflow Definition JSON Schema 4.1.0

从独立模块后端发布

模块方法调用 Hosted Service 或其他独立后端,并由后端在业务事务成功后发布事件时,应让 Runtime 把发布 目标作为一对只读能力交付给后端:

  • <eventName>_event_url:当前 Runtime 生成的事件方法 URL。
  • <eventName>_event_authorization:只允许调用该 Runtime 能力的完整 Authorization 值。

如果 methodBody 需要引用这两个值,先在 module.jsonpropertyDefinition 中声明同名属性。URL 必须 只读;Authorization 必须同时只读且敏感:

{
  "propertyDefinition": [
    {
      "name": "orderStatusChanged_event_url",
      "type": {
        "@type": "DataType",
        "type": "string",
        "nullable": true
      },
      "description": "由当前 Runtime 生成的 orderStatusChanged 发布地址。",
      "isSensitive": false,
      "readOnly": true,
      "required": false
    },
    {
      "name": "orderStatusChanged_event_authorization",
      "type": {
        "@type": "DataType",
        "type": "string",
        "nullable": true
      },
      "description": "由当前 Runtime 生成的 orderStatusChanged 发布授权。",
      "isSensitive": true,
      "readOnly": true,
      "required": false
    }
  ]
}

再在调用后端的 HTTP 方法中用 position: "property" 映射。下列 Header 名是模块与自身后端约定的示例, 不是平台保留 Header:

{
  "header": {
    "X-Module-Event-Url": {
      "required": true,
      "position": "property",
      "key": "orderStatusChanged_event_url"
    },
    "X-Module-Event-Authorization": {
      "required": true,
      "position": "property",
      "key": "orderStatusChanged_event_authorization"
    }
  }
}

后端从受信任的模块调用中读取这对值,向 URL 发送符合事件 paramDefinitions 的 JSON,并把 Authorization 值原样放入请求头。URL 已经是完整事件方法地址;不要追加内部路径,也不要把 Authorization 改造成另一种 token。

POST <orderStatusChanged_event_url>
Authorization: <orderStatusChanged_event_authorization>
Content-Type: application/json

{
  "orderId": "order-123",
  "status": "approved",
  "occurredAt": 1788537600000
}

安全与生命周期规则

  • URL 与 Authorization 是当前 Runtime 颁发的一对能力,必须成对使用、成对更新;不得跨工作区或跨 Runtime 复用。
  • 不允许终端用户提交任意事件 URL 或 Authorization。浏览器、表单、工作流输入和普通业务 API 都不应包含 这两个字段。
  • Authorization 不进入日志、响应、事件载荷、任务参数或普通数据库字段。异步后端确需跨请求保存时,应写入 该 Runtime 安装实例的敏感配置存储,并在 Runtime 属性交付更新时替换。
  • 后端不得按工作区 ID、项目 ID、域名规则或环境名称拼接发布地址,也不得直接调用内部事件服务。
  • 发布成功只证明事件已被接受;后续动作还取决于目标 Runtime 中是否安装并启用了匹配的 Event Trigger 或 订阅,以及其投递与重试状态。

发布前验证

  1. 从精确 ModuleVersion 回读事件名和 paramDefinitions,确认来自预期 Git commit。
  2. 检查 Bundle Manifest 精确引用该 ModuleVersion,并包含需要的 Event Trigger 资源。
  3. 安装或升级 Bundle 后,从目标 Runtime 回读事件方法;不要只检查项目工作区文件。
  4. 分别验证工作流 emit_event 和后端回调所需的入口;不使用生产凭据做本地硬编码测试。
  5. 发送一条带稳定业务幂等键的测试事件,再检查订阅触发、Webhook/动作结果和失败重试。

事件声明的 JSON 结构与版本演进规则见模块定义开发

本页内容