fix: 写队列满时 Close 不再与 enqueue 死锁

This commit is contained in:
Nixevol
2026-09-30 19:18:29 +08:00
parent 443a6c6f59
commit aa38cfc76b
3 changed files with 166 additions and 9 deletions
+10
View File
@@ -1728,3 +1728,13 @@ issue #3 未关闭,`feat/fix-3-downlink-deadlock` 未合入 `main`。下面是
- 原因:终态回执、超限后的后续 pending、撤回腾出窗口后都依赖再唤醒,否则空闲在线端收不到。
- 备选方案:在同一次 `PushPending` 里循环扫完整 pending 表(否决,指令要求合并唤醒下一轮)。
- 影响:仅 `internal/app/message/`;相关单测见 `review_r3_65_test.go`。
### 复审修复 R3-03
1. **写队列满时 Close 不再与 enqueue 死锁**
- 日期:2026-09-30
- 原条款:issue #67;停机需 Drain/Close 在超时内返回;已入队任务仍由写 goroutine 处理完。
- 实际做法:Queue 增加 closing 信号。enqueue 在持 sendMu.RLock 时 select 同时等待 q.ch、closing 与 ctx.Done(),通道满时不再无限阻塞。Close 先 Swap(closed) 并 close(closing) 唤醒在途发送方释放读锁,再在写锁内 close(q.ch),最后等 loop 退出。不向已关闭 channel 发送。
- 原因:通道满时并发 Do 占着读锁堵在发送上,Close 的写锁拿不到,停机卡死;未提交的在途写也会丢。
- 备选方案:入队改为非阻塞,满则立即 ErrBusy(否决:改变背压语义,正常高峰会误伤提交)。
- 影响:仅 internal/store/queue.go 与测试;不改迁移编号。