docs(05): 锚点补记十一——W40 普通发送未连接时进队列(主人定案落地),并登记 REST 未覆盖与三条待办
记下这一批的口径与证据,供下一个会话接续: - 分支 feat/W40-send-queue-offline(基线 e60ae7a),代码与测试提交 df9fc85;未合并、未推送。 - 证据:assembleDebug 成功;testDebugUnitTest 1118 / 0 失败 / 0 错误 / 0 跳过(83 套件)。 本批没有真机回归。 - 判据:wsSendOutcome 三档(Dispatched / Queued / Failed);补发触发点是连接状态流变成 Connected 那一刻,无轮询;顺序 = 用户发送先后顺序;只发一次的保证点是队头加出队恰好一次, 第二道是复用同一个 clientMsgId。 - 状态表达:不新增第七态(等连接仍是 ③ 排队中),气泡小标加成「排队中 · 还没连上」, 另有一条柔和的 sendQueueNotice 告知(一轮队列只说一次,Offline 那一档说的是 重新登录 / 检查服务器地址)。 - REST 通道(长文 / 图片 / 附件)本批未覆盖,仍走回滚加既有网络错误文案,理由与影响面写在 补记里。 - 待办里更新了四条:真机回归、REST 要不要也排队(需主人定案)、Offline 立刻告知、 以及那一处刻意未动的失败文案字面量。
This commit is contained in:
1 parent
df9fc85f76
commit
67b2e58fdf
1 file changed
+28
@@ -870,3 +870,31 @@ curl -s -X PATCH "$BASE/api/v1/sessions/$SID" -H "Authorization: Bearer $TOK" \
|
||||
> 3. `Offline` 立刻告知(不等 3 秒)。
|
||||
> 4. **W38/W39 的真机回归**:W38 已验(补记九);W39 这三条只在真机上扫一眼即可(触发条件都少见)。
|
||||
> 5. 旧账:子会话流程(主人搁置)、图片/工具卡实机验证(后端未配工具)、**相册多选→分享**(图片路径仍需真机;App 一个权限都没声明 ⇒ adb 造不出可读 URI,这条**只能**走真机或驱动相册 UI)。
|
||||
|
||||
> ## ★★ 锚点补记十一(2026-10-05 · W40:普通发送「未连接 ⇒ 进队列」,不再回滚)
|
||||
>
|
||||
> ### 状态
|
||||
> - worktree 分支 `feat/W40-send-queue-offline`(基线 `e60ae7a`),分支提交 **`df9fc85`**;**未合并、未推送**(主树与 `origin/android` 都没动)。
|
||||
> - 本批证据:`assembleDebug` 成功;`testDebugUnitTest` **1118 测试 / 0 失败 / 0 错误 / 0 跳过**(83 套件)。**没有真机回归**(这一批只有单测与编译证据)。
|
||||
> - 净变化:W39 加的 `SendFailureMessageTest`(4 条)**删掉**,其断言改成新事实后并入新的 `SendQueueTest`(21 条)⇒ 1101 − 4 + 21 = 1118。
|
||||
>
|
||||
> ### ① 主人的裁决落地:未连接 ⇒ 进队列(上一批的「待办 1」已定案并做完)
|
||||
> - 新纯函数 `wsSendOutcome(sent, connection)`(`ui/chat/SendQueue.kt`)三档:`Dispatched`(帧交给 socket;**成功路径一个字没动**)/ `Queued`(未就绪四档:Idle / Connecting / Reconnecting / Offline)/ `Failed`(连接就绪却仍发不出去 ⇒ 今天那条 `rollback` + `SEND_FAILED_MESSAGE`)。
|
||||
> - `deliver` 的 WS 分支**只改「未就绪」这一支**:不回滚、不进 `error` 横幅,改由 `queueForConnection` 留在待发态(`ChatUiState.queuedForConnection`:条目只有键与并行声明,正文仍从气泡上现取)。
|
||||
> - **触发点**:`onConnectionChanged` 里 `connection == WsState.Connected` 那一格(由 `socket.state` 驱动,**无轮询**)+入队后的竞态兜底。
|
||||
> - **顺序**:FIFO = 用户发送的先后顺序;补发只看队头。**只发一次**:队头 + 出队恰好一次(`dropQueuedSend`);第二道是补发复用同一个 `clientMsgId`(服务端 `chat_duplicate` 判重)。`flushQueuedSends` 是同步函数(无挂起点),两个触发点不会交错。
|
||||
> - ⚠️ **已知边界**:打断声明(`interrupt{scope:"current"}`)不随补发重放(补发时在跑的那一轮早已不是用户按发送时看到的那一个);内容仍只在**进程内存**里,一直连不上又杀进程就丢(既有语义)。
|
||||
>
|
||||
> ### ② 状态表达:③ 排队中 + 小标「还没连上」,**不新增第七态**
|
||||
> - `phaseOf(待发气泡)` 的 ③ 判据扩为「收到过入队回执 **或** 本端因未连接留住」;气泡小标由新纯函数 `pendingBubbleFooter` 给:`排队中 · 还没连上`(服务端忙时排队仍是 `排队中`)——挂在气泡上而不是只靠告知,因为告知 8 秒就收走,而这是会持续几十秒的状态。
|
||||
> - 柔和告知走**新通道** `ChatUiState.sendQueueNotice`(与 `shareNotice` 分开:两条说不同的动作):`SEND_QUEUED_NOTICE = "还没连上,这条排队等着,连上后自动发出"`;`Offline` 那一档换 `SEND_QUEUED_OFFLINE_NOTICE = "现在处于离线,需要重新登录或检查服务器地址;这条还没发出去,已排队不会丢"`(**不提**「连上」「自动发」)。**不刷屏**:一轮「队列从空到空」只说一次。
|
||||
>
|
||||
> ### ③ REST 通道(长文 / 图片 / 附件)**未覆盖**,仍是回滚 + 网络错误文案
|
||||
> 理由:它给不出「未连接」这个信号(只有一次网络错误,请求可能已被服务端收到),且补发要重跑图片重编码与附件上传(本地 URI 授权可能已失效)。影响面仅这一条通道。
|
||||
>
|
||||
> ### 待办(更新)
|
||||
> 1. **W40 的真机回归**:断网发普通消息 ⇒ 应看到「排队中 · 还没连上」+ 柔和告知(**没有**红色横幅、输入栏不退回)⇒ 恢复连接 ⇒ 自动补发且只落库一条。
|
||||
> 2. REST 通道(长文 / 图片 / 附件)未连接时要不要也排队——需主人定案(代价见 ③)。
|
||||
> 3. `Offline` 立刻告知(不等 3 秒)——W39 遗留,未动。
|
||||
> 4. **未纳入新判据的一处字面量**:REST 回执被拒那条路仍是 `rejected.message.ifBlank { "发送失败,请重试" }`,刻意未动。
|
||||
> 5. 旧账:子会话流程(主人搁置)、图片/工具卡实机验证(后端未配工具)、**相册多选→分享**(只能走真机或驱动相册 UI)。
|
||||
Reference in new issue
Block a user