Merge pull request #3546 from nslogx/fix/platform-quota-five-platforms

fix: allow five platform quota updates
This commit is contained in:
Wesley Liddick
2026-07-01 14:07:08 +08:00
committed by GitHub
7 changed files with 34 additions and 32 deletions
@@ -3812,7 +3812,7 @@ func slotOf(s *service.DefaultPlatformQuotaSetting, win string) *float64 {
return nil
}
// equalPlatformQuotaSettings reports whether two platform-quota maps are identical across all 12 slots.
// equalPlatformQuotaSettings reports whether two platform-quota maps are identical across all allowed slots.
func equalPlatformQuotaSettings(before, after map[string]*service.DefaultPlatformQuotaSetting) bool {
for _, platform := range service.AllowedQuotaPlatforms {
b := before[platform]
@@ -3,6 +3,7 @@ package admin
import (
"context"
"errors"
"fmt"
"log/slog"
"math"
"strconv"
@@ -629,8 +630,8 @@ func (h *UserHandler) UpdateUserPlatformQuotas(c *gin.Context) {
return
}
if len(req.Quotas) > 4 {
response.BadRequest(c, "quotas length must be <= 4")
if len(req.Quotas) > len(service.AllowedQuotaPlatforms) {
response.BadRequest(c, fmt.Sprintf("quotas length must be <= %d", len(service.AllowedQuotaPlatforms)))
return
}
seen := make(map[string]struct{}, len(req.Quotas))
@@ -749,7 +750,7 @@ func (h *UserHandler) UpdateUserPlatformQuotas(c *gin.Context) {
// 失效 cache:对全部允许的 platform 统一 invalidate。
// Trade-off:精确失效(仅 req 涉及平台 + 被软删平台)需 upsert 前额外 ListByUser,
// 增加一次 DB 查询和逻辑复杂度。由于 AllowedQuotaPlatforms 只有 4 个元素,
// 增加一次 DB 查询和逻辑复杂度。由于 AllowedQuotaPlatforms 数量很少,
// 全量 invalidate 的额外开销可接受,且能可靠覆盖软删除场景。
if h.billingCache != nil {
for _, p := range service.AllowedQuotaPlatforms {
@@ -98,7 +98,10 @@ func TestUpdateUserPlatformQuotas_Success(t *testing.T) {
body := `{"quotas":[
{"platform":"anthropic","daily_limit_usd":10.0,"weekly_limit_usd":null,"monthly_limit_usd":100.0},
{"platform":"openai","daily_limit_usd":null,"weekly_limit_usd":null,"monthly_limit_usd":null}
{"platform":"openai","daily_limit_usd":80.0,"weekly_limit_usd":300.0,"monthly_limit_usd":null},
{"platform":"gemini","daily_limit_usd":null,"weekly_limit_usd":null,"monthly_limit_usd":null},
{"platform":"antigravity","daily_limit_usd":null,"weekly_limit_usd":null,"monthly_limit_usd":null},
{"platform":"grok","daily_limit_usd":null,"weekly_limit_usd":null,"monthly_limit_usd":null}
]}`
c, w := putReq(t, body)
h.UpdateUserPlatformQuotas(c)
@@ -109,10 +112,10 @@ func TestUpdateUserPlatformQuotas_Success(t *testing.T) {
if len(repo.upsertCalls) != 1 {
t.Fatalf("UpsertForUser should be called once, got %d", len(repo.upsertCalls))
}
if repo.upsertCalls[0].userID != 42 || len(repo.upsertCalls[0].records) != 2 {
if repo.upsertCalls[0].userID != 42 || len(repo.upsertCalls[0].records) != len(service.AllowedQuotaPlatforms) {
t.Errorf("unexpected upsert call: %+v", repo.upsertCalls[0])
}
// 缓存失效:请求中 2 个 platform + 软删除的 3 个 platform(gemini, antigravity, grok)= 5 次
// 缓存失效:按全部允许平台统一失效。
if len(cache.deleteCalls) != 5 {
t.Errorf("expected 5 cache delete calls, got %d: %+v", len(cache.deleteCalls), cache.deleteCalls)
}
@@ -154,7 +157,7 @@ func TestUpdateUserPlatformQuotas_RejectsNegativeLimit(t *testing.T) {
func TestUpdateUserPlatformQuotas_RejectsTooManyEntries(t *testing.T) {
h := buildTestHandler(&upsertCapturingQuotaRepo{}, &billingCacheStub{})
body := `{"quotas":[
{"platform":"anthropic"},{"platform":"openai"},{"platform":"gemini"},{"platform":"antigravity"},{"platform":"anthropic"}
{"platform":"anthropic"},{"platform":"openai"},{"platform":"gemini"},{"platform":"antigravity"},{"platform":"grok"},{"platform":"anthropic"}
]}`
c, w := putReq(t, body)
h.UpdateUserPlatformQuotas(c)