feat: expose result subscription HTTP and WebSocket APIs
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
| 任务冻结策略与 Worker `retryable` | P3 安全重试已实现 | [安全重试](retries.md) |
|
||||
| `/v1/tasks/{task_id}:cancel` 与 `task.cancel` 通知 | P3 运行中取消已实现 | [取消及 SDK 场景](cancellation.md) |
|
||||
| `/v1/schedules`、不可变版本、暂停/恢复及触发查询 | P3 已实现 | [计划接口与 SDK 场景](schedules.md) |
|
||||
| `/v1/events/connect` 及订阅管理 | 持久化核心已实现;HTTP/WSS 和 SDK 尚未接入 | [订阅核心及边界](../09-result-subscription-core.md) |
|
||||
| `/v1/subscriptions` 及管理、交付查询与重试 | 已实现 HTTP、管理 SDK 和完整管理示例 | [订阅手册](subscriptions.md) |
|
||||
| `/v1/events/connect` | 已实现服务端 WSS 与消息 Schema;消费 SDK 待交付 | [消息协议](subscriptions.md#5-websocket-建连与边界) |
|
||||
| `/v1/workflows` 与流程管理 | 计划 P4–P5,尚未实现 | [流程接口规划](workflows.md) |
|
||||
|
||||
未实现路由返回 404。健康检查就绪不表示任务执行、定时调度或流程引擎已经可用。
|
||||
|
||||
@@ -58,4 +58,4 @@ P2 增加 workers:connect 和 workers:consume。bootstrap 只有显式提供 --w
|
||||
|
||||
P3 应用额度管理新增 `application:resources:read` 和 `application:resources:manage`。只有显式 `--resource-access` 才授予,作用域是所属应用的全部命名空间,普通队列管理不能替代。查询返回聚合计数,不开放其他命名空间的任务数据。`bootstrap --application-id <现有应用ID>` 可由数据库管理员增加命名空间,与 `--application` 二选一;验证应用启用及额度记录存在后,同事务创建新资源,所有秘密交付约定保持不变。应用默认未终结上限 1000000、并发 10000、开始速率 100000/秒;详见 [应用共享配额](application-resources.md)。
|
||||
|
||||
P3 结果订阅核心新增 `events:read`、`events:manage` 和 `events:consume`,bootstrap 仅显式 `--event-access` 时授予。订阅绑定创建凭据与单个队列,不能用同命名空间的另一张凭据消费或管理。当前 HTTP/WSS 和独立 SDK 尚未接入,详见 [订阅核心边界](../09-result-subscription-core.md)。
|
||||
P3 结果订阅核心新增 `events:read`、`events:manage` 和 `events:consume`,bootstrap 仅显式 `--event-access` 时授予。订阅绑定创建凭据与单个队列,不能用同命名空间的另一张凭据消费或管理。当前 HTTP/WSS 和管理 SDK 已接入;消费 SDK、凭据重绑继续开发,详见 [订阅接口](subscriptions.md)。
|
||||
|
||||
327
docs/api/subscriptions.md
Normal file
327
docs/api/subscriptions.md
Normal file
@@ -0,0 +1,327 @@
|
||||
# 可靠结果订阅 HTTP 与 WebSocket
|
||||
|
||||
状态:已实现服务端 HTTP/WSS、管理 SDK 和管理示例。事件连接 SDK、自动重连消费器、持久化 Inbox 示例及真实进程强杀验证继续开发,完整 P3 订阅验收尚未完成。[存储语义与升级边界](../09-result-subscription-core.md),[本阶段验证](../reports/phase-3-result-subscription-transport.md)。
|
||||
|
||||
## 1. 授权与共同规则
|
||||
|
||||
所有 HTTP 请求使用 Authorization: Bearer 请求头,管理写请求还需要稳定的 Idempotency-Key。生产通过 HTTPS/WSS 接入;本地示例可使用回环 HTTP。凭据、交付秘密不能放在 URL。请求不接受自报 namespace_id、application_id 或 credential_id。
|
||||
|
||||
订阅固定绑定创建凭据和一个队列。除动作权限外,每次操作都验证队列范围和订阅所有者。另一张凭据即使属于相同命名空间也不能操作此订阅;凭据重新绑定尚未开放。bootstrap 使用显式 --event-access 才授予三个事件动作。
|
||||
|
||||
| 方法与路径 | 权限 | SDK 方法 |
|
||||
| --- | --- | --- |
|
||||
| POST /v1/subscriptions | events:manage | CreateSubscription |
|
||||
| GET /v1/subscriptions?queue_id=... | events:read | ListSubscriptions |
|
||||
| GET /v1/subscriptions/{id} | events:read | GetSubscription |
|
||||
| POST /v1/subscriptions/{id}:configure | events:manage | ConfigureSubscription |
|
||||
| GET /v1/subscriptions/{id}/deliveries | events:read | ListEventDeliveries |
|
||||
| GET /v1/subscriptions/{id}/deliveries/{delivery_id} | events:read | GetEventDelivery |
|
||||
| POST /v1/subscriptions/{id}/deliveries/{delivery_id}:retry | events:manage | RetryEventDelivery |
|
||||
| GET /v1/events/connect(WebSocket Upgrade) | events:consume | 连接 SDK 待交付,可按下文协议接入 |
|
||||
|
||||
HTTP 使用统一 request_id + data/error 信封,响应带 X-Request-ID 和 Cache-Control: no-store。管理请求 8 秒服务端超时、JSON 最大 512 KiB。未知字段、大小写别名、重复 JSON 键、未知或重复查询参数均被拒绝。计数/版本以规范十进制字符串传输,不能带正号、前导零或小数。
|
||||
|
||||
除两个列表接口外,不接受查询参数。没有公开硬删除、修改过滤、修改历史起点或替换所属凭据的接口。
|
||||
|
||||
## 2. 创建订阅
|
||||
|
||||
POST /v1/subscriptions,Content-Type: application/json,Idempotency-Key: 调用方持久化的操作身份。
|
||||
|
||||
| 字段 | 要求 |
|
||||
| --- | --- |
|
||||
| name | 必填,1–128 个 ASCII 字符,首字符字母/数字,其余允许字母/数字/点/下划线/连字符;命名空间内唯一 |
|
||||
| queue_id | 必填,32 位小写十六进制 ID;固定为该队列 |
|
||||
| types | 可选数组,省略或 [] 表示四类全部;否则必须为四类的非重复子集 |
|
||||
| from_sequence | 可选 uint64 十进制字符串;省略或 null 从创建时已提交流头之后开始;"0" 从现存结果日志开始 |
|
||||
| max_pending | 可选整数,省略或 0 使用 100,自定义 1–1000 |
|
||||
| max_attempts | 可选整数,省略或 0 使用 20,自定义 1–100 |
|
||||
|
||||
四类结果为 task.succeeded、task.failed、task.cancelled、task.needs_review。安全重试的 task.requeued 不在此集合。needs_review 不是成功或确定失败;同一个任务以后可能产生另一条权威结果,必须按 event_id 去重,不能只按 task_id 去重。
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "object-results",
|
||||
"queue_id": "11111111111111111111111111111111",
|
||||
"types": ["task.succeeded", "task.failed", "task.cancelled", "task.needs_review"],
|
||||
"max_pending": 100,
|
||||
"max_attempts": 20
|
||||
}
|
||||
```
|
||||
|
||||
首次成功 HTTP 201;相同身份/内容重报 HTTP 200,deduplicated=true,返回原快照。请求尚未确认时必须保留原键、原请求和原 from_sequence,不能换键重新追到最新位置。
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id": "77777777777777777777777777777777",
|
||||
"data": {
|
||||
"subscription": {
|
||||
"id": "22222222222222222222222222222222",
|
||||
"queue_id": "11111111111111111111111111111111",
|
||||
"credential_id": "88888888888888888888888888888888",
|
||||
"name": "object-results",
|
||||
"revision": "1",
|
||||
"enabled": true,
|
||||
"types": ["task.cancelled", "task.failed", "task.needs_review", "task.succeeded"],
|
||||
"cursor_sequence": "12",
|
||||
"pending_count": 0,
|
||||
"max_pending": 100,
|
||||
"max_attempts": 20,
|
||||
"created_at": "2026-09-17T10:00:00Z",
|
||||
"updated_at": "2026-09-17T10:00:00Z"
|
||||
},
|
||||
"deduplicated": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
类型集合按固定顺序规范化。cursor_sequence 表示已经扫描并建立交付记录的位置,**不是确认水位**。pending_count 包含等待、租约中和次数耗尽记录。配置 revision 不随物化/ACK 用量变化。
|
||||
|
||||
每命名空间最多 64 个订阅。from_sequence 不能超过已提交流头,也不能早于已清理的保留边界。现存日志从迁移 000013 启用,不补造此前的任务结果。
|
||||
|
||||
## 3. 查询和控制订阅
|
||||
|
||||
GET /v1/subscriptions/{id} 返回 data 为上节 subscription 对象,HTTP 200。幂等写回执是原状态;查询接口才读取当前配置和用量。
|
||||
|
||||
GET /v1/subscriptions 必须带 queue_id;可选 limit=1–100(省略 20)和 cursor。返回 data.items 为 subscription 数组,另有可选 next_cursor。列表只包含当前凭据在这个队列中的订阅,按 created_at DESC、id DESC 排序。游标不能换队列、凭据或命名空间使用。
|
||||
|
||||
POST /v1/subscriptions/{id}:configure 只改变 enabled,要求以下三个字段全部显式提供:
|
||||
|
||||
```json
|
||||
{
|
||||
"expected_revision": "1",
|
||||
"enabled": false,
|
||||
"reason": "receiver maintenance"
|
||||
}
|
||||
```
|
||||
|
||||
expected_revision 必须匹配当前配置版本,reason 为非空字符串、最多 1024 个 Unicode 字符。成功 HTTP 200,data 为 SubscriptionResult,即 `{subscription, deduplicated}`。恢复时设置 enabled=true,并使用新的操作身份与查询取得的版本。重复原命令必须保留第一次的版本,不能把响应的新版本放回原键。
|
||||
|
||||
暂停停止新物化/领取,保留已有结果、交付和租约;仍允许消费者确认已可靠保存的结果。暂停不意味着已发消息被撤回。相同布尔值的新命令仍作为新的带审计配置操作增加版本。
|
||||
|
||||
## 4. 交付历史、详情和人工重试
|
||||
|
||||
GET /v1/subscriptions/{id}/deliveries 支持 limit、cursor,以及可选 state:PENDING、LEASED、ACKED、EXPIRED。不带 state 返回全部已物化交付。返回 data 为 `{items: [...], next_cursor?: "..."}`,按创建时间及 ID 倒序分页。游标绑定订阅、凭据、命名空间与状态过滤,不能混用。
|
||||
|
||||
列表项 EventDelivery 的字段如下:
|
||||
|
||||
| 字段 | 类型与含义 |
|
||||
| --- | --- |
|
||||
| id / subscription_id / event_id | 32 位小写十六进制身份;同一事件向同一订阅的交付 ID 不因补发变化 |
|
||||
| sequence | 来源结果序号,uint64 字符串 |
|
||||
| revision | 交付并发版本,uint64 字符串;领取、恢复、确认和人工重试时变化 |
|
||||
| state | 四种交付状态 |
|
||||
| created_at / available_at | UTC 创建时间和最早可重发时间 |
|
||||
| lease_epoch | uint64 字符串,从未发送时为 "0",每次领取递增 |
|
||||
| lease_until | 可选 UTC 租约截止;仅 LEASED 存在 |
|
||||
| attempts / attempt_budget | 已用次数和累计预算,整数;人工重试不重置 attempts |
|
||||
| acknowledged_at | 可选 UTC 首次有效确认时间,仅 ACKED 存在 |
|
||||
|
||||
GET /v1/subscriptions/{id}/deliveries/{delivery_id} 返回 data 为 `{delivery: EventDelivery, event: ResultEvent}`。事件字段见下一节的 event.deliver 示例。该接口不返回 lease_secret 或 token_digest,也不允许跨订阅查询同一个交付 ID。
|
||||
|
||||
分页是运维查询,不是一致性快照或可靠消费协议。并发状态变化可能改变过滤结果,不能通过列表遍历代替交付确认。未物化结果尚无交付记录,不会出现在该列表。
|
||||
|
||||
POST /v1/subscriptions/{id}/deliveries/{delivery_id}:retry 只允许 EXPIRED,带稳定 Idempotency-Key:
|
||||
|
||||
```json
|
||||
{
|
||||
"expected_revision": "3",
|
||||
"reason": "receiver persistence failure repaired",
|
||||
"additional_attempts": 2
|
||||
}
|
||||
```
|
||||
|
||||
成功 HTTP 200,data 为 `{delivery: EventDelivery, deduplicated: false}`;交付变为 PENDING,追加 1–100 次预算,累计预算最多 1000000。已有次数、代次、事件身份和积压占用不归零。重报返回原回执,不再追加。
|
||||
|
||||
当前租约恢复由启用订阅的后续领取触发;没有消费者或订阅暂停时,租约可能在截止后仍显示 LEASED。查询本身不修改状态,人工重试也不能绕过状态要求。独立后台清扫、历史清理和凭据安全重绑仍待后续完成。
|
||||
|
||||
## 5. WebSocket 建连与边界
|
||||
|
||||
入口 /v1/events/connect,Sec-WebSocket-Protocol: orbit.events.v1,Authorization 使用请求头。拒绝 URL 参数及跨来源 Origin;不使用 Cookie。升级前先验证 events:consume,随后 hello 再校验具体订阅所有者和队列范围。读权限不能替代消费权限,消费权限也不隐含读取所有历史的权限。
|
||||
|
||||
每帧为一个文本 JSON,最大 512 KiB,禁用压缩。固定 protocol_version="1",message_id 是调用方生成的 32 位随机十六进制标识。服务端响应使用新的 message_id,以 reply_to 关联请求。message_id 只用于相关性;ACK 的持久化去重依据是交付 ID、代次和秘密。
|
||||
|
||||
连接后 5 秒内发送 hello,不能带 session_id、reply_to 或 error:
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "1",
|
||||
"type": "events.hello",
|
||||
"message_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"body": {"subscription_id": "22222222222222222222222222222222", "capacity": 1}
|
||||
}
|
||||
```
|
||||
|
||||
capacity 必填整数 1–32,表示该连接允许持有的交付数量,在数据库事务内校验。首版连接期间不可修改,调整容量需要关闭并重新连接。订阅仍可以由同一凭据的多个连接共同消费,各连接竞争持久化交付。
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "1",
|
||||
"type": "events.welcome",
|
||||
"message_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
"reply_to": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"session_id": "44444444444444444444444444444444",
|
||||
"body": {
|
||||
"session_id": "44444444444444444444444444444444",
|
||||
"subscription_id": "22222222222222222222222222222222",
|
||||
"capacity": 1,
|
||||
"lease_duration_ms": 30000,
|
||||
"heartbeat_interval_ms": 15000,
|
||||
"server_time": "2026-09-17T10:00:00Z",
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
session_id 由服务端生成,仅标识当前连接。后续请求必须带这个值。断线后不恢复旧连接身份,也不删除租约;新的连接使用新 session_id,但可以用上一连接保留的最近证明核对 ACK。
|
||||
|
||||
节点最多 128 条事件连接。领取池全局最多 4 个在途、每应用最多 1 个;等待加在途最多 128,按认证应用及订阅轮转。每连接读队列 4、写队列 8,每个扫描轮次最多排入 4 次领取。慢 SQL 领取和控制收发分开;领取权及容量仍由 MySQL 决定。
|
||||
|
||||
这些是当前节点保护参数,不是生产吞吐承诺,也没有跨节点全局公平或应用连接席位预留。Worker 连接使用独立入口、协议与连接池。
|
||||
|
||||
## 6. 交付与可靠确认
|
||||
|
||||
服务端先持久化交付租约,再发送 event.deliver。以下 lease_secret 是全零字节编码的文档占位值,实际由服务端生成随机秘密:
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "1",
|
||||
"type": "event.deliver",
|
||||
"message_id": "cccccccccccccccccccccccccccccccc",
|
||||
"session_id": "44444444444444444444444444444444",
|
||||
"body": {
|
||||
"delivery": {
|
||||
"created_at": "2026-09-17T10:00:00Z",
|
||||
"id": "33333333333333333333333333333333",
|
||||
"subscription_id": "22222222222222222222222222222222",
|
||||
"event_id": "55555555555555555555555555555555",
|
||||
"sequence": "13",
|
||||
"revision": "2",
|
||||
"state": "LEASED",
|
||||
"available_at": "2026-09-17T10:00:00Z",
|
||||
"lease_epoch": "1",
|
||||
"lease_until": "2026-09-17T10:00:30Z",
|
||||
"attempts": 1,
|
||||
"attempt_budget": 20
|
||||
},
|
||||
"event": {
|
||||
"id": "55555555555555555555555555555555",
|
||||
"sequence": "13",
|
||||
"type": "task.cancelled",
|
||||
"aggregate_kind": "task",
|
||||
"aggregate_id": "66666666666666666666666666666666",
|
||||
"aggregate_revision": "2",
|
||||
"occurred_at": "2026-09-17T10:00:00Z",
|
||||
"details": {"state": "CANCELLED", "reason": "CANCEL_REQUESTED"},
|
||||
"snapshot": {
|
||||
"schema_version": 1,
|
||||
"task_id": "66666666666666666666666666666666",
|
||||
"queue_id": "11111111111111111111111111111111",
|
||||
"state": "CANCELLED",
|
||||
"revision": "2",
|
||||
"effect_uncertain": false
|
||||
}
|
||||
},
|
||||
"lease_secret": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
snapshot 还可包含业务 result 和 current_attempt_id;result 用原始 JSON 文本保留数值精度。details 是来源事件的元信息,按事件类型演进;不含任务输入或交付秘密。结果快照不可变。
|
||||
|
||||
接收方应在本地事务中使用 event.id 作为 Inbox 唯一键,完成可靠保存或业务事务后才确认。不得先 ACK 再把消息仅放到内存队列。耗时业务可先可靠写入本地 Outbox,再由业务侧继续处理。平台首版不提供交付续租;30 秒租约用于尽快持久化接收结果。
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "1",
|
||||
"type": "event.ack",
|
||||
"message_id": "dddddddddddddddddddddddddddddddd",
|
||||
"session_id": "44444444444444444444444444444444",
|
||||
"body": {
|
||||
"delivery_id": "33333333333333333333333333333333",
|
||||
"epoch": "1",
|
||||
"lease_secret": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "1",
|
||||
"type": "ack",
|
||||
"message_id": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
||||
"reply_to": "dddddddddddddddddddddddddddddddd",
|
||||
"session_id": "44444444444444444444444444444444",
|
||||
"body": {
|
||||
"delivery_id": "33333333333333333333333333333333",
|
||||
"event_id": "55555555555555555555555555555555",
|
||||
"epoch": "1",
|
||||
"acknowledged_at": "2026-09-17T10:00:01Z",
|
||||
"deduplicated": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
确认响应丢失时,保留原 delivery_id、epoch 和 lease_secret 重报;可以在新连接中使用新的 session_id 重报。已确认时返回原 acknowledged_at 和 deduplicated=true,不再次扣减积压或写重复确认审计。
|
||||
|
||||
租约到期后,最新证明若尚未被新代次替换,仍可迟到确认。新的发送产生后旧证明返回 DELIVERY_LEASE_LOST;接收方已保存的 Inbox 仍保留,下一次收到同一事件时检查已有记录,再用新交付证明 ACK。不能把旧证明替换为猜测的新代次。
|
||||
|
||||
交付是至少一次语义;连接关闭、写超时、ACK 响应丢失都可能导致重复。不得依靠本地内存“见过”集合宣称业务恰好一次。
|
||||
|
||||
## 7. 心跳、错误和关闭
|
||||
|
||||
客户端建议每 15 秒发送一次 events.ping,body 为 {};服务端以 ack 回复 `{server_time, enabled}`,同时重新校验凭据与订阅范围。收到结果也不能替代客户端心跳。连续 60 秒没有有效读取到客户端帧会关闭连接;写入超时为 5 秒。暂停中的订阅仍能连接、心跳和确认已有交付。
|
||||
|
||||
```json
|
||||
{
|
||||
"protocol_version": "1",
|
||||
"type": "events.ping",
|
||||
"message_id": "ffffffffffffffffffffffffffffffff",
|
||||
"session_id": "44444444444444444444444444444444",
|
||||
"body": {}
|
||||
}
|
||||
```
|
||||
|
||||
错误帧使用 type="error" 与 error={code,message},无 body。请求错误带 reply_to;后台领取发现授权失效或其他错误时可以没有 reply_to。hello 绑定失败时没有 session_id,绑定后的错误带当前 session_id。非法信封、二进制消息或错误会话直接按 WebSocket 1008 关闭,超限消息由 WebSocket 关闭。
|
||||
|
||||
| 错误码 | HTTP 状态 / WSS 行为 |
|
||||
| --- | --- |
|
||||
| INVALID_ARGUMENT | 400;命令体无效时可返回 WSS error,非法信封直接关闭 |
|
||||
| UNAUTHENTICATED | 401;已连接时发送错误并关闭 |
|
||||
| PERMISSION_DENIED | 403;已连接时发送错误并关闭 |
|
||||
| NOT_FOUND | 404;订阅/交付不在凭据与父资源范围;连接内发生时关闭 |
|
||||
| STATE_CONFLICT | 409;版本、状态或累计预算不允许操作 |
|
||||
| IDEMPOTENCY_CONFLICT | 409;同键内容不同 |
|
||||
| SUBSCRIPTION_LIMIT | 409;命名空间订阅数达到 64 |
|
||||
| EVENT_HISTORY_EXPIRED | 410;WSS 领取发现历史缺口则报错并关闭,不静默跳到最新位置 |
|
||||
| DELIVERY_LEASE_LOST | WSS ACK 证明已替换或无效;连接保留,等待新交付或核对历史 |
|
||||
| PROTOCOL_REQUIRED | 升级前 426,必须指定 orbit.events.v1 |
|
||||
| CAPACITY_EXCEEDED | 升级前 429,Retry-After: 1 |
|
||||
| UNAVAILABLE | 503;WSS 中数据库等临时失败会报错并关闭,重连仍保留原交付/确认身份 |
|
||||
|
||||
断线/节点关闭不清除持久化交付。领取恢复会在预算内补发,或保留 EXPIRED。客户端关闭时应先完成自己的本地持久化、保存未核对 ACK 的证明,再关闭连接;平台不能保证物理撤回已经写入网络的消息。
|
||||
|
||||
## 8. 管理 SDK 与完整可运行示例
|
||||
|
||||
已实现的 Go 类型和方法:[类型](../../sdk/go/subscription_types.go)、[管理方法](../../sdk/go/subscriptions.go)。下面是应用函数内片段,client 已由 NewClient 创建,key 应先持久化:
|
||||
|
||||
```go
|
||||
created, err := client.CreateSubscription(ctx, key, orbit.CreateSubscriptionRequest{
|
||||
Name: "object-results",
|
||||
QueueID: queueID,
|
||||
MaxPending: 100,
|
||||
MaxAttempts: 20,
|
||||
})
|
||||
if err != nil { return err }
|
||||
current, err := client.GetSubscription(ctx, created.Subscription.ID)
|
||||
if err != nil { return err }
|
||||
_, err = client.ConfigureSubscription(ctx, current.ID, pauseKey, orbit.ConfigureSubscriptionRequest{
|
||||
ExpectedRevision: current.Revision,
|
||||
Enabled: false,
|
||||
Reason: "receiver maintenance",
|
||||
})
|
||||
return err
|
||||
```
|
||||
|
||||
[完整管理示例](../../sdk/go/examples/subscriptions/main.go) 的启动、输入输出、失败和保留规则见 [场景文档](../examples/subscriptions.md)。它演示管理与幂等,不启动结果消费者。WSS 连接 SDK、自动重连和持久化 Inbox 示例仍在下一阶段开发,不能把测试中的原始 WebSocket 辅助代码当成正式 SDK。
|
||||
|
||||
机器可读消息契约见 [events.schema.json](../../protocol/eventsv1/events.schema.json),使用 Draft 2020-12,clientFrame/serverFrame 分方向约束。运行时额外拒绝重复 JSON 键、超范围 uint64 及非规范 base64url。Schema 不代替授权、状态机、租约及事务校验。
|
||||
Reference in New Issue
Block a user