事件流
面向组织和项目活动的服务器发送事件。
Kisenon 将组织和项目活动以
服务器发送事件
的形式流式推送。打开一个长期的 HTTP 连接,设置
Accept: text/event-stream,每当有变化发生时,控制平面就会推送一个
JSON 信封。
控制台的实时活动视图正是基于这同一个流来驱动的。
端点
两条路由,都是 SSE:
| 路由 | 作用域 |
|---|---|
GET /v1/events | 调用方组织中的每个项目。 |
GET /v1/projects/{id}/events | 单个项目。 |
两者都位于 https://api.test.kisenon.com 之下。如果项目不属于您的
组织,项目作用域的路由会返回 404,因此存在性永远不会跨组织泄露。
身份验证
与其他每个控制平面调用相同的 Bearer 凭据:一个 API 密钥
(nsk_…)或一个由 cp 签名的 web JWT。参见 身份验证。
调用方必须是该组织的成员;非成员会得到一个
403。
事件信封
每个事件都是一个形态稳定的 JSON 对象:
| 字段 | 类型 | 含义 |
|---|---|---|
id | string | ULID(26 个字符)。单调递增;同时充当 SSE 事件 id。 |
type | string | 事件类型,例如 operation.updated.v1。 |
source | string | 产生事件的子系统,例如 operations。 |
org_id | string | 所属组织(UUID 文本)。 |
project_id | string? | 所属项目;组织级事件中省略。 |
region_id | string | 发出该事件的区域。 |
at | string | RFC 3339 时间戳。 |
data | object | 类型特定的负载。 |
信封形态永远不会以不兼容的方式变更。新字段是增量式的,而新的事件
变体会获得一个新的 type(例如未来的 operation.updated.v2),
而不是改变现有的。
事件类型
如今控制平面发布一种应用事件类型:
operation.updated.v1(source 为operations)—— 一个操作改变了 生命周期状态。data携带operation_id、action、status, 以及当该行仍然存在时,branch_id、endpoint_id、error和initiator。
broker 还发出三种内部控制事件(source 为 _broker):
resume.gap.v1—— 您的Last-Event-ID比 broker 的缓冲区更旧; 有事件被遗漏了。通过 REST 重新获取完整状态,然后继续流式接收。overflow.v1—— 您的客户端读取太慢而被丢弃;data.dropped统计丢失的事件数。重新连接并重新获取完整状态。error.v1—— 一个生产者侧的错误标记。
audit、invitations 和 billing 这几个 source 是预留的,但尚不
发出事件;随着那些工作线落地,这个列表会增长。
续传
每个事件的 id 就是它的 SSE id,因此一个原生的 EventSource 会在
重连时自动将最后一个作为 Last-Event-ID 头重新发送,broker 会重放
其后缓冲的一切。您也可以显式传入它:
Last-Event-ID: 01JX5N4R8ZT2W7Q9V3B1C6D8EF如果间隔比 broker 的内存环更宽,您会收到一个 resume.gap.v1 而非
重放。把它(以及 overflow.v1)当作"您遗漏了事件":通过 REST API
重新获取受影响的状态,然后从最新的 id 续传流式接收。
示例
curl -N -H "Authorization: Bearer $KISENON_API_KEY" \
-H "Accept: text/event-stream" \
https://api.test.kisenon.com/v1/events一个流式事件看起来像:
id: 01JX5N4R8ZT2W7Q9V3B1C6D8EF
event: operation.updated.v1
data: {"id":"01JX5N4R8ZT2W7Q9V3B1C6D8EF","type":"operation.updated.v1","source":"operations","org_id":"6f1d2c3b-4a59-4e87-9b10-2d3e4f5a6b7c","project_id":"prj_4c1d9e2a7b3f5c8d0e1f2a3b","region_id":"home-proxmox","at":"2026-06-03T12:00:00Z","data":{"operation_id":"op_77a1","action":"create_branch","status":"finished","branch_id":"br_91c2"}}以 : 开头的行(例如 : keepalive)是心跳注释;忽略它们。
在控制台中
控制台的实时活动视图消费这同一个流(通过控制台来源代理,因为浏览器
的 EventSource 无法设置 Authorization 头)。在 resume.gap.v1
或 overflow.v1 时,它会通过 REST 重新获取完整状态 —— 正是上面的
约定。如果您正在构建自己的消费者,请照此行事。