docs: 写入 K-00 SDK 行为约定附录
This commit is contained in:
+33
-2
@@ -958,7 +958,7 @@ close()
|
||||
1. WebSocket 到 `路径/mqtt`,子协议 `mqtt`。裸 TCP 只在选项里显式打开时使用。浏览器页面是 HTTPS 时,服务器也必须用 TLS:浏览器不允许 HTTPS 页面连 `ws://` 或请求 `http://`。
|
||||
2. 每次连接都带 Clean Start,包括重连。Go 的 autopaho 只在第一次连接使用 `CleanStartOnInitialConnection`,必须用 `ConnectPacketBuilder` 在每一次连接把 Clean Start 设为 true,会话过期间隔设为 0。
|
||||
3. 订阅 down,发 `hello`,等到成功响应。连接超时默认 30 秒(autopaho 默认 10 秒,要改):服务器重启后大量端同时重连,密码校验要排队。
|
||||
4. 重连退避:1 秒起,加倍,上限 30 秒,加减 30% 抖动。稳定在线 60 秒后把退避恢复到 1 秒。
|
||||
4. 重连退避:见本节附录「SDK 行为约定」。
|
||||
5. 会话令牌:用密码连上后,把握手响应里的 `session_token` 通过 `onSession` 交给应用,之后自动重连都用这个令牌;应用下次启动可以直接用保存的令牌 `connect`。SDK 自己不落盘保存令牌和密码。
|
||||
6. 停止重连的情况:收到 `fatal`;被 `0x8E` 接管;CONNACK 为 `0x86` 用户名或密码错误、`0x87` 未授权、`0x8A` 已封禁(3.1.1 为返回码 4、5)。这时事件 `auth_failed` 带原因:用令牌连接被拒为 `session_invalid`(在别处登录过、令牌过期、密码被改或重置、已退出登录、编号被停用或删除),用密码被拒为 `bad_credentials`。其他失败,包括网络错误、`0x88` 服务器不可用、`0x89` 服务器忙、连接被直接关闭,都继续重连。
|
||||
|
||||
@@ -966,7 +966,7 @@ close()
|
||||
|
||||
- 发送队列在内存,默认最多 1000 条,包括已发出但没收到 `resp` 的。连不上时 `send` 入队;重连后按原消息号、原请求内容再交。
|
||||
- `sendAt` 在调用 `send` 时就换算成 `send_at_ms`,重交时不重算,否则请求指纹变了会被当成冲突。
|
||||
- 同时在途(已发出、没收到 `resp`)的请求不超过 100 个。发送收到 `rate_limited` 时按退避自动重交,不算失败;其他请求收到 `rate_limited` 直接返回给应用。
|
||||
- 同时在途(已发出、没收到 `resp`)的请求不超过 100 个。发送收到 `rate_limited` 时按附录「SDK 行为约定」自动重交,不算失败;其他请求收到 `rate_limited` 直接返回给应用。
|
||||
- 进程退出则队列丢失。SDK 停止重连(被踢、认证失败、`logout`、`close`)时,队列里的发送全部以对应错误结束。
|
||||
- 其他调用在未握手时返回未连接。
|
||||
|
||||
@@ -1019,6 +1019,37 @@ close()
|
||||
14. 仅 JS:浏览器页面和服务器不同域名时,注册和 WebSocket 连接都成功。
|
||||
15. 会话令牌:密码登录后收到令牌;断开后用令牌重连成功;另一处用密码登录后,原来那处用旧令牌重连被拒(`session_invalid`)且不再重连;`logout` 后令牌失效。
|
||||
|
||||
### 附录:SDK 行为约定
|
||||
|
||||
四种语言同一套对外语义。实现以本附录为准,不以任何一套现有 SDK 为参照。Issue K-00 (#57) 及第二轮审查「补充」条目已并入下表。
|
||||
|
||||
| 项 | 约定 |
|
||||
|---|---|
|
||||
| 首次连接超时 | 默认 30 秒内没完成握手:停止重连,返回 `not_connected`;Client 可再次调用 connect |
|
||||
| 认证失败错误码 | 直接用原因:`bad_credentials`、`session_invalid`、`disabled`、`deleted`、`password_reset`、`taken_over`、`rate_limited`;事件 `auth_failed` / `kicked` 带同一原因 |
|
||||
| 顶号原因名 | MQTT DISCONNECT `0x8E` 一律报 `taken_over`,不报 `"0x8E"` |
|
||||
| 服务器关闭 | DISCONNECT `0x8B` 按可重试处理,继续重连 |
|
||||
| 本地队列满 | 统一 `queue_full`,不用服务端的 `quota_exceeded` |
|
||||
| 请求返回值 | 只返回 resp 的 `data`,不返回整个信封 |
|
||||
| sendAt 与 delay 同时给 | 本地返回 `bad_request`(PRD F11) |
|
||||
| 停止重连后再 send | 立即以停止原因失败,不入队 |
|
||||
| logout | 服务端请求失败(含离线)时把错误返回给应用;本地照常停止重连、清空令牌、断开传输;队列里的发送按「停止重连后再 send」的停止原因结束,并发 `offline` 事件 |
|
||||
| 时长参数 | 毫秒时长和时间戳一律用 64 位整数(Java 用 `long` / `Long`) |
|
||||
| max_receive_bytes 小于 1024 | 本地返回 `bad_request` |
|
||||
| URL 映射 | `http`→`ws`、`https`→`wss`;`ws`/`wss` 原样;`mqtt`/`mqtts` 只在显式开启裸 TCP 选项时允许;路径为空或 `/` 时用 `/mqtt`,否则按原路径 |
|
||||
| 取消与超时 | 尚未发出的条目取消即出队;已发出的返回「结果未知」错误(错误码 `result_unknown`),应用应以同一消息号重试 |
|
||||
| rate_limited 重交退避 | 每条发送单独计数:第 n 次等待 `min(1 秒 × 2^(n-1), 30 秒) × 随机(0.7, 1.3)`,成功后清零。每次重交(包括断线后的重交)都重新生成 `rid` 并重新序列化帧;消息 `id`、正文和 `send_at_ms` 保持不变 |
|
||||
| 重连退避 | 只维护一个连续失败计数 n(n ≥ 1)。第 n 次等待 `min(1 秒 × 2^(n-1), 30 秒) × 随机(0.7, 1.3)`。只有应用调用 connect 后的第一次连接可以不等待;已建立的连接断开后,第一次重连也按 n=1 等约 1 秒。连接尝试失败时 n 加 1;连上后不足 60 秒又断开,也按一次失败计(n 加 1);稳定在线满 60 秒后断开,n 重置为 1。不能再另把 base 翻倍。连接超时覆盖等 CONNACK 的时间 |
|
||||
| 心跳 | 默认 30 秒 |
|
||||
| Receive Maximum | CONNECT 不带该属性 |
|
||||
| 默认请求超时 | 非发送请求默认 60 秒 |
|
||||
|
||||
重连退避标称间隔(去掉抖动):n=1…6 为 1、2、4、8、16、30 秒。rate_limited 重交用同一套标称间隔,但按**该条发送**自己的计数,与连接失败计数无关。
|
||||
|
||||
四套 SDK 为上表每一项使用同名用例(Go `TestK00*`,JS/Python `test_k00_*`,Java `testK00*`):
|
||||
|
||||
`FirstConnectTimeout`、`AuthErrorCodes`、`TakenOverReason`、`Disconnect8BRetryable`、`QueueFull`、`RequestReturnsData`、`SendAtAndDelayConflict`、`SendAfterStopped`、`LogoutReturnsError`、`DurationInt64`、`MaxReceiveBytesMin`、`URLMapping`、`CancelUnsent`、`RateLimitedBackoff`、`ReconnectBackoff`、`KeepaliveDefault`、`NoReceiveMaximum`。
|
||||
|
||||
## 10. 无 SDK 的设备
|
||||
|
||||
使用 MQTT 5 客户端(例如 ESP-IDF 的 mqtt,走 WebSocket 或 TCP)。ClientID 和用户名是端编号,密码是登录密码。订阅 `nix/c/{编号}/down`,向 `nix/c/{编号}/up` 发第 6 节的 JSON。收到 `msg` 后处理完发 `ack`。用「from + id」去重,已确认过的再到达时再回一次 `ack`。在 `hello` 里按自己的接收缓冲声明 `max_receive_bytes`(不小于 1024)。裸设备要么实现 `receipt_ack`,要么发送时带 `receipt:false`,否则未确认的回执会占满推送窗口。
|
||||
|
||||
@@ -1153,6 +1153,15 @@
|
||||
- 备选:ack 发后不等 `resp`;未采用,以免丢「ack 结果当 revoked」语义。
|
||||
- 影响:行为更接近文档;单测仍绿。
|
||||
|
||||
### 复审修复 K-00
|
||||
|
||||
- 日期:2026-09-30
|
||||
- 原条款:PRD F19「四种 SDK 行为一致」;DEVELOPMENT 第 9 节重连退避原文过简;issue #57 及第二轮审查修订。
|
||||
- 实际做法:在 DEVELOPMENT 第 9 节增加附录「SDK 行为约定」,四套 README 各加摘要。重连退避按 `min(1s×2^(n-1), 30s)×随机(0.7,1.3)`、只维护一个计数 n;不以现有 JS 实现为参照。rate_limited 与断线重交每次新 rid;logout 失败返回应用;时长用 64 位整数;CONNECT 不带 Receive Maximum;0x8B 可重试;顶号原因 `taken_over`。
|
||||
- 原因:四套对外语义不一致;第二轮审查核实 JS 退避双重翻倍,照搬会把错误带进四套。
|
||||
- 备选方案:统一采用旧 S1.3 状态机;否决。
|
||||
- 影响:K-01 至 K-04 按本附录实现;本条只改文档。
|
||||
|
||||
## SDK 二 S2
|
||||
|
||||
### S2-PY/JAVA 1–3 2026-09-30
|
||||
|
||||
Reference in New Issue
Block a user