模块事件与发布机制
区分事件声明、发布和订阅,并通过当前 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.json 的 propertyDefinition 中声明同名属性。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 或 订阅,以及其投递与重试状态。
发布前验证
- 从精确 ModuleVersion 回读事件名和
paramDefinitions,确认来自预期 Git commit。 - 检查 Bundle Manifest 精确引用该 ModuleVersion,并包含需要的 Event Trigger 资源。
- 安装或升级 Bundle 后,从目标 Runtime 回读事件方法;不要只检查项目工作区文件。
- 分别验证工作流
emit_event和后端回调所需的入口;不使用生产凭据做本地硬编码测试。 - 发送一条带稳定业务幂等键的测试事件,再检查订阅触发、Webhook/动作结果和失败重试。
事件声明的 JSON 结构与版本演进规则见模块定义开发。