feat(gateway): 双模式用户消息队列 — 串行队列 + 软性限速

新增 UMQ (User Message Queue) 双模式支持:
- serialize: 账号级分布式串行锁 + RPM 自适应延迟(严格限流)
- throttle: 仅 RPM 自适应前置延迟,不阻塞并发(软性限速)

后端:
- config: 新增 Mode 字段,保留 Enabled 向后兼容
- service: 新增 UserMessageQueueService(Lua 锁/延迟算法/清理 worker)
- repository: 新增 UserMsgQueueCache(Redis Lua acquire/release/force-release)
- handler: 新增 UserMsgQueueHelper(SSE ping + 等待循环 + throttle)
- gateway: 按 mode 分支集成 serialize/throttle 逻辑
- lint: 修复 gofmt rewrite rules、errcheck 类型断言、staticcheck QF1012

前端:
- 三态选择器 UI(关闭/软性限速/串行队列)替代 toggle 开关
- BulkEdit 支持 null 语义(不修改)
- i18n 中英文文案

通过 6 轮专家评审(42 次 review)、golangci-lint、单元测试、集成测试。
This commit is contained in:
QTom
2026-03-03 01:02:39 +08:00
parent 7abec1888f
commit a9285b8a94
21 changed files with 1099 additions and 15 deletions

View File

@@ -994,7 +994,7 @@ func (s *SettingService) GetMinClaudeCodeVersion(ctx context.Context) string {
}
}
// singleflight: 同一时刻只有一个 goroutine 查询 DB其余复用结果
result, _, _ := minVersionSF.Do("min_version", func() (any, error) {
result, err, _ := minVersionSF.Do("min_version", func() (any, error) {
// 二次检查,避免排队的 goroutine 重复查询
if cached, ok := minVersionCache.Load().(*cachedMinVersion); ok {
if time.Now().UnixNano() < cached.expiresAt {
@@ -1020,10 +1020,14 @@ func (s *SettingService) GetMinClaudeCodeVersion(ctx context.Context) string {
})
return value, nil
})
if s, ok := result.(string); ok {
return s
if err != nil {
return ""
}
return ""
ver, ok := result.(string)
if !ok {
return ""
}
return ver
}
// SetStreamTimeoutSettings 设置流超时处理配置