fix: 应用 xhigh 代码评审的跨端修复
ci / server (push) Failing after 13s
ci / design-tokens (push) Failing after 11s

来自 xhigh code review 的正确性/健壮性修复,覆盖全部五端:
- server:鉴权 fail-closed、计量交叉校验与配额扣穿处理、WS 网关并发与关闭顺序、
  billing 行锁、redis Lua 过期与设备槽刷新、config 解析
- desktop:会话 epoch 防串话、WS 重连与 401 处理、api 客户端复用、统一 usePoll 轮询
- android:握手时序、请求头封装、账户状态派生、按需重组
- ios:finalize 宽限、串行采集、错误文案服务端优先、删除死代码 CommitController

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-13 11:50:08 +08:00
parent 50b49f3cbe
commit b5ab92a57e
42 changed files with 2125 additions and 469 deletions
+35 -10
View File
@@ -35,21 +35,25 @@ func TestAllowSessionWindow(t *testing.T) {
}
}
func TestAllowAudioSecondsWindow(t *testing.T) {
// TestAudioWindowExhausted 复用生产路径(AudioWindowExhausted 只查 + RecordAudioSeconds 记账)。
func TestAudioWindowExhausted(t *testing.T) {
r := rdb(t)
ctx := context.Background()
now := time.Now()
// 1700s 放行
if ok, _ := AllowAudioSeconds(ctx, r, "dev1", 1700, now); !ok {
t.Fatal("1700s should pass")
// 初始未满
if full, _ := AudioWindowExhausted(ctx, r, "dev1", now); full {
t.Fatal("fresh window should not be exhausted")
}
// 再 100s(累计 1800)放行
if ok, _ := AllowAudioSeconds(ctx, r, "dev1", 100, now.Add(time.Second)); !ok {
t.Fatal("cumulative 1800s should pass")
// 记满后窗口耗尽(AudioWindowExhausted 只查不记,val=0sum>limit 才算满)
if err := RecordAudioSeconds(ctx, r, "dev1", 1801, now); err != nil {
t.Fatal(err)
}
// 再 1s 超限拒绝
if ok, _ := AllowAudioSeconds(ctx, r, "dev1", 1, now.Add(2*time.Second)); ok {
t.Fatal("1801s should be rejected")
if full, _ := AudioWindowExhausted(ctx, r, "dev1", now.Add(time.Second)); !full {
t.Fatal("window should be exhausted after exceeding 1800s")
}
// 其他设备不受影响
if full, _ := AudioWindowExhausted(ctx, r, "dev2", now); full {
t.Fatal("other device window should not be exhausted")
}
}
@@ -78,3 +82,24 @@ func TestDeviceSlot(t *testing.T) {
t.Fatal("acquire after release should pass")
}
}
// TestRefreshDeviceSlot 仅持有者能续期;非持有者续期无效(17D)。
func TestRefreshDeviceSlot(t *testing.T) {
r := rdb(t)
ctx := context.Background()
if ok, err := AcquireDeviceSlot(ctx, r, "dev1", "s1"); err != nil || !ok {
t.Fatalf("acquire should pass: %v", err)
}
// 持有者续期成功
if ok, err := RefreshDeviceSlot(ctx, r, "dev1", "s1"); err != nil || !ok {
t.Fatalf("holder refresh should succeed: ok=%v err=%v", ok, err)
}
// 非持有者续期失败
if ok, _ := RefreshDeviceSlot(ctx, r, "dev1", "s2"); ok {
t.Fatal("non-holder refresh should fail")
}
// 续期未释放槽位:他人仍抢不到
if ok, _ := AcquireDeviceSlot(ctx, r, "dev1", "s2"); ok {
t.Fatal("slot should still be held after refresh")
}
}