Merge pull request #6969 from ouchihao/codex/issue-5882-peak-rate-validation

fix(groups): return bad request for invalid peak-rate settings
This commit is contained in:
Wesley Liddick
2026-09-11 14:01:14 +08:00
committed by GitHub
2 changed files with 63 additions and 2 deletions
+2 -2
View File
@@ -469,7 +469,7 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn
// 先归一化(非订阅分组清空高峰配置、清洗停用状态下的脏字段)再校验,与 UpdateGroup 同一收口。
peakRateEnabled, peakStart, peakEnd, peakRateMultiplier := NormalizePeakRateConfig(subscriptionType, input.PeakRateEnabled, input.PeakStart, input.PeakEnd, peakRateMultiplier)
if err := ValidatePeakRateConfig(subscriptionType, peakRateEnabled, peakStart, peakEnd, peakRateMultiplier); err != nil {
return nil, err
return nil, infraerrors.BadRequest("INVALID_PEAK_RATE_CONFIG", err.Error())
}
profitMinMargin := 0.0
@@ -867,7 +867,7 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd
// 防止单独修改 start/end 导致最终 start>=end 等非法配置入库。与 CreateGroup 同一收口。
group.PeakRateEnabled, group.PeakStart, group.PeakEnd, group.PeakRateMultiplier = NormalizePeakRateConfig(group.SubscriptionType, group.PeakRateEnabled, group.PeakStart, group.PeakEnd, group.PeakRateMultiplier)
if err := ValidatePeakRateConfig(group.SubscriptionType, group.PeakRateEnabled, group.PeakStart, group.PeakEnd, group.PeakRateMultiplier); err != nil {
return nil, err
return nil, infraerrors.BadRequest("INVALID_PEAK_RATE_CONFIG", err.Error())
}
if input.ProfitControlEnabled != nil {
group.ProfitControlEnabled = *input.ProfitControlEnabled
@@ -1145,6 +1145,67 @@ func TestAdminService_UpdateGroup_ClearsReasoningPolicyForUnsupportedPlatform(t
require.Empty(t, repo.updated.ReasoningEffortMappings)
}
func TestAdminService_CreateGroup_InvalidPeakRateReturnsBadRequest(t *testing.T) {
repo := &groupRepoStubForAdmin{}
svc := &adminServiceImpl{groupRepo: repo}
_, err := svc.CreateGroup(context.Background(), &CreateGroupInput{
Name: "subscription-group",
RateMultiplier: 1,
Platform: PlatformOpenAI,
SubscriptionType: SubscriptionTypeSubscription,
PeakRateEnabled: true,
PeakStart: "20:00",
PeakEnd: "08:30",
})
require.ErrorContains(t, err, "peak_end")
require.Equal(t, http.StatusBadRequest, infraerrors.Code(err))
require.Equal(t, "INVALID_PEAK_RATE_CONFIG", infraerrors.Reason(err))
require.Nil(t, repo.created)
}
func TestAdminService_UpdateGroup_PeakRateValidation(t *testing.T) {
tests := []struct {
name string
input UpdateGroupInput
wantErr bool
}{
{"cross-day window", UpdateGroupInput{PeakStart: ptrString("20:00"), PeakEnd: ptrString("08:30")}, true},
{"partial update invalidates window", UpdateGroupInput{PeakEnd: ptrString("08:30")}, true},
{"partial update keeps valid window", UpdateGroupInput{PeakEnd: ptrString("19:00")}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := &groupRepoStubForAdmin{getByID: &Group{
ID: 1,
Name: "subscription-group",
Platform: PlatformOpenAI,
Status: StatusActive,
SubscriptionType: SubscriptionTypeSubscription,
PeakRateEnabled: true,
PeakStart: "14:00",
PeakEnd: "18:00",
PeakRateMultiplier: 3,
}}
svc := &adminServiceImpl{groupRepo: repo}
_, err := svc.UpdateGroup(context.Background(), 1, &tt.input)
if tt.wantErr {
require.ErrorContains(t, err, "peak_end")
require.Equal(t, http.StatusBadRequest, infraerrors.Code(err))
require.Equal(t, "INVALID_PEAK_RATE_CONFIG", infraerrors.Reason(err))
require.Nil(t, repo.updated)
} else {
require.NoError(t, err)
require.NotNil(t, repo.updated)
require.Equal(t, "19:00", repo.updated.PeakEnd)
}
})
}
}
func TestAdminService_UpdateGroup_ClearsPeakRateWhenChangingToStandard(t *testing.T) {
existingGroup := &Group{
ID: 1,