Skip to content

fix: OAuth 401 不再永久锁死账号,改用临时不可调度实现自动恢复#723

Open
zqq-nuli wants to merge 1 commit intoWei-Shaw:mainfrom
zqq-nuli:fix/oauth-401-temp-unschedulable
Open

fix: OAuth 401 不再永久锁死账号,改用临时不可调度实现自动恢复#723
zqq-nuli wants to merge 1 commit intoWei-Shaw:mainfrom
zqq-nuli:fix/oauth-401-temp-unschedulable

Conversation

@zqq-nuli
Copy link

@zqq-nuli zqq-nuli commented Mar 2, 2026

Summary

  • OAuth 账号收到 401 时,原逻辑同时设置 expires_at=now()SetError(),但 TokenRefreshService.listActiveAccounts() 只查询 status=active 的账号,导致 error 状态的账号永远无法被刷新服务拾取,expires_at=now() 实际上是死代码
  • 修复: OAuth 401 使用 SetTempUnschedulable 替代 SetError,保持 status=active,让刷新服务能自动恢复账号
  • 将 Antigravity 平台的错误容错机制推广到所有 OAuth 平台

Changes

  • config.go: 新增 oauth_401_cooldown_minutes 配置项(默认 10 分钟)
  • ratelimit_service.go: OAuth 账号 401 时调用 SetTempUnschedulable 替代 handleAuthError/SetError;非 OAuth 账号(APIKey)行为不变
  • token_refresh_service.go:
    • 刷新成功后同步清除 DB 和 Redis 中的临时不可调度状态
    • isNonRetryableRefreshError 检查从 Antigravity 推广到所有平台
    • 可重试错误耗尽后不再 SetError,下个刷新周期继续重试
  • wire.go / wire_gen.go: 注入 TempUnschedCacheTokenRefreshService

恢复流程

OAuth 401 → temp_unschedulable(10min) + expires_at=now + cache invalidated
  → 账号保持 status="active"
  → 刷新服务(5分钟周期) → NeedsRefresh=true → 尝试刷新:
    ├── 成功 → ClearTempUnschedulable(DB+Redis) → 账号自动恢复
    ├── 不可重试错误(invalid_grant) → SetError → 永久禁用(正确行为)
    └── 可重试错误(网络超时) → 仅记日志 → 下个周期重试

Test plan

  • ratelimit_service_401_test.go: OAuth 401 调用 SetTempUnschedulable(非 SetError)
  • ratelimit_service_401_test.go: 非 OAuth(APIKey)401 行为不变
  • token_refresh_service_test.go: 刷新成功清除 temp_unschedulable(DB + Redis)
  • token_refresh_service_test.go: 所有平台不可重试错误 SetError
  • token_refresh_service_test.go: 可重试错误耗尽不标记 error
  • 所有相关单元测试通过: go test -tags unit ./internal/service/ -run "401|TokenRefresh" -v

OAuth 账号收到 401 时,原逻辑同时设置 expires_at=now() 和 SetError(),
但刷新服务只查询 status=active 的账号,导致 error 状态的账号永远无法
被刷新服务拾取,expires_at=now() 实际上是死代码。

修复:
- OAuth 401 使用 SetTempUnschedulable 替代 SetError,保持 status=active
- 新增 oauth_401_cooldown_minutes 配置项(默认 10 分钟)
- 刷新成功后同步清除 DB 和 Redis 中的临时不可调度状态
- 不可重试错误检查(invalid_grant 等)从 Antigravity 推广到所有平台
- 可重试错误耗尽后不再标记 error,下个刷新周期继续重试

恢复流程:
OAuth 401 → temp_unschedulable + expires_at=now → 刷新服务拾取
  → 成功: 清除 temp_unschedulable → 自动恢复
  → invalid_grant: SetError → 永久禁用
  → 网络错误: 仅记日志 → 下周期重试
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant