并发队列与 Lane 状态机实战:session/global 双层排队
这一章把“并发控制”写成可复刻的状态机:同会话保序、全局限流、重启后可恢复。
入口(概念版):
对应源码入口(可选)
src/process/command-queue.tssrc/agents/pi-embedded-runner/lanes.tssrc/gateway/server-lanes.tssrc/agents/pi-embedded-runner/runs.ts
核心数据结构(你实现时建议显式保留)
LaneState:queue/activeTaskIds/maxConcurrent/draining/generationQueueEntry:enqueuedAt/warnAfterMs/onWait(只告警,不取消)
关键流程(入队 → drain → 完成回收)
- 入队后立即触发 drain(不要等下一次事件)。
draining防重入,避免并发 pump 造成重复拉起。- 失败分支也要继续 pump(否则队列会饿死/僵死)。
reset/generation(重启后不僵死的关键)
in-process 重启或异常中断时,旧任务的 finally 可能不会执行。
generation 的作用是:旧回调回写时发现 generation 不匹配,就忽略写回,避免污染新状态。
失败场景与排障入口
- 同会话乱序:确认是否有 session lane 串行,以及
maxConcurrent是否被意外改大。 - 队列卡死:检查失败分支是否继续 pump;检查是否因重入导致
draining永久为 true。 - probe lane 日志轰炸:探针任务失败应静默,避免误导性噪音。
验收清单
- 同一 session 连发多条消息,回复顺序稳定。
- 两个 session 可并发执行,不互相阻塞。
- reset 后积压任务能继续 drain(不僵死)。