From 51f354f5c298c82c42e2918616cb0fe4adb1f364 Mon Sep 17 00:00:00 2001 From: wucm667 Date: Thu, 23 Jul 2026 12:24:30 +0000 Subject: [PATCH] fix(grok): avoid pool cooldown on 5xx --- .../internal/service/openai_gateway_grok.go | 2 +- .../service/openai_gateway_grok_test.go | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/backend/internal/service/openai_gateway_grok.go b/backend/internal/service/openai_gateway_grok.go index d887ff73fc..059b74402a 100644 --- a/backend/internal/service/openai_gateway_grok.go +++ b/backend/internal/service/openai_gateway_grok.go @@ -1363,7 +1363,7 @@ func (s *OpenAIGatewayService) handleGrokAccountUpstreamError(ctx context.Contex case http.StatusTooManyRequests: // updateGrokUsageSnapshot installs both runtime and durable rate-limit state. default: - if statusCode >= 500 { + if statusCode >= 500 && !account.IsPoolMode() { s.tempUnscheduleGrok(ctx, account, 2*time.Minute, "grok upstream temporary error") } } diff --git a/backend/internal/service/openai_gateway_grok_test.go b/backend/internal/service/openai_gateway_grok_test.go index 3a8e347332..b2b9367dba 100644 --- a/backend/internal/service/openai_gateway_grok_test.go +++ b/backend/internal/service/openai_gateway_grok_test.go @@ -2475,6 +2475,43 @@ func TestHandleGrokAccountUpstreamErrorTempUnschedulesNonRateLimitStates(t *test } } +func TestHandleGrokAccountUpstreamError5xxRespectsPoolMode(t *testing.T) { + t.Run("pool mode keeps scheduling state", func(t *testing.T) { + account := &Account{ + ID: 611, + Platform: PlatformGrok, + Type: AccountTypeAPIKey, + Credentials: map[string]any{ + "pool_mode": true, + }, + } + repo := &grokQuotaAccountRepo{} + svc := &OpenAIGatewayService{accountRepo: repo} + + svc.handleGrokAccountUpstreamError(context.Background(), account, http.StatusBadGateway, nil, nil) + + require.False(t, svc.isOpenAIAccountRuntimeBlocked(account)) + require.Zero(t, repo.tempUnschedCalls) + require.Nil(t, account.TempUnschedulableUntil) + require.Empty(t, account.TempUnschedulableReason) + }) + + t.Run("non-pool mode keeps two minute cooldown", func(t *testing.T) { + account := &Account{ID: 612, Platform: PlatformGrok, Type: AccountTypeAPIKey} + repo := &grokQuotaAccountRepo{} + svc := &OpenAIGatewayService{accountRepo: repo} + before := time.Now() + + svc.handleGrokAccountUpstreamError(context.Background(), account, http.StatusBadGateway, nil, nil) + + require.True(t, svc.isOpenAIAccountRuntimeBlocked(account)) + require.Equal(t, 1, repo.tempUnschedCalls) + require.Equal(t, account.ID, repo.lastTempUnschedID) + require.Equal(t, "grok upstream temporary error", repo.lastTempUnschedReason) + require.WithinDuration(t, before.Add(2*time.Minute), repo.lastTempUnschedUntil, time.Second) + }) +} + func TestHandleGrokAccountUpstreamError429SetsRateLimitedFromRetryAfter(t *testing.T) { account := &Account{ID: 61, Platform: PlatformGrok, Type: AccountTypeOAuth} repo := &grokQuotaAccountRepo{}