From 1dd3521190117a8b8240597e8425d8c3ae6f5c59 Mon Sep 17 00:00:00 2001 From: song Date: Sun, 4 Jan 2026 11:49:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(antigravity):=20=E4=BC=98=E5=8C=96=20token?= =?UTF-8?q?=20=E5=88=B7=E6=96=B0=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 不可重试错误(invalid_grant等)直接标记 error,不重试 - 其他错误仅记录日志,不标记 error(可能是临时网络问题) - 仅影响 Antigravity 账户,其他平台保持原有逻辑 --- .../internal/service/token_refresh_service.go | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/backend/internal/service/token_refresh_service.go b/backend/internal/service/token_refresh_service.go index 76ca61fd..3ed35f04 100644 --- a/backend/internal/service/token_refresh_service.go +++ b/backend/internal/service/token_refresh_service.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "strings" "sync" "time" @@ -171,6 +172,15 @@ func (s *TokenRefreshService) refreshWithRetry(ctx context.Context, account *Acc return nil } + // Antigravity 账户:不可重试错误直接标记 error 状态并返回 + if account.Platform == PlatformAntigravity && isNonRetryableRefreshError(err) { + errorMsg := fmt.Sprintf("Token refresh failed (non-retryable): %v", err) + if setErr := s.accountRepo.SetError(ctx, account.ID, errorMsg); setErr != nil { + log.Printf("[TokenRefresh] Failed to set error status for account %d: %v", account.ID, setErr) + } + return err + } + lastErr = err log.Printf("[TokenRefresh] Account %d attempt %d/%d failed: %v", account.ID, attempt, s.cfg.MaxRetries, err) @@ -183,11 +193,37 @@ func (s *TokenRefreshService) refreshWithRetry(ctx context.Context, account *Acc } } - // 所有重试都失败,标记账号为error状态 - errorMsg := fmt.Sprintf("Token refresh failed after %d retries: %v", s.cfg.MaxRetries, lastErr) - if err := s.accountRepo.SetError(ctx, account.ID, errorMsg); err != nil { - log.Printf("[TokenRefresh] Failed to set error status for account %d: %v", account.ID, err) + // Antigravity 账户:其他错误仅记录日志,不标记 error(可能是临时网络问题) + // 其他平台账户:重试失败后标记 error + if account.Platform == PlatformAntigravity { + log.Printf("[TokenRefresh] Account %d: refresh failed after %d retries: %v", account.ID, s.cfg.MaxRetries, lastErr) + } else { + errorMsg := fmt.Sprintf("Token refresh failed after %d retries: %v", s.cfg.MaxRetries, lastErr) + if err := s.accountRepo.SetError(ctx, account.ID, errorMsg); err != nil { + log.Printf("[TokenRefresh] Failed to set error status for account %d: %v", account.ID, err) + } } return lastErr } + +// isNonRetryableRefreshError 判断是否为不可重试的刷新错误 +// 这些错误通常表示凭证已失效,需要用户重新授权 +func isNonRetryableRefreshError(err error) bool { + if err == nil { + return false + } + msg := strings.ToLower(err.Error()) + nonRetryable := []string{ + "invalid_grant", // refresh_token 已失效 + "invalid_client", // 客户端配置错误 + "unauthorized_client", // 客户端未授权 + "access_denied", // 访问被拒绝 + } + for _, needle := range nonRetryable { + if strings.Contains(msg, needle) { + return true + } + } + return false +}