fix: 修复 Token 自动刷新失败导致持续 504/429 错误

- 修复 Scheduler 刷新使用错误的默认模型名 (grok-4-1-thinking-1129 → grok-3),
  避免 basic token 查询配额时返回 403
- 调整 Scheduler 启动后立即执行首轮刷新,而非等待整个 interval (2-8h)
- 移除刷新失败分支中的 mark_synced() 调用,使失败 token 在下一轮
  循环中被重新尝试而非被跳过
- Token 池耗尽时自动触发 refresh_cooling_tokens(),尝试恢复
  冷却中的 token,而非直接返回 429
This commit is contained in:
piexian committed 2026-02-10 18:36:19 +08:00
1 parent f6b9bc37af
commit d11b059943
3 files changed
+20 -12

No files matched your search

+15 -6
View File
@@ -394,12 +394,21 @@ class ChatService:
break
if not token:
raise AppException(
message="No available tokens. Please try again later.",
error_type=ErrorType.RATE_LIMIT.value,
code="rate_limit_exceeded",
status_code=429,
)
logger.info("No available tokens, attempting to refresh cooling tokens...")
result = await token_mgr.refresh_cooling_tokens()
if result.get("recovered", 0) > 0:
for pool_name in ModelService.pool_candidates_for_model(model):
token = token_mgr.get_token(pool_name)
if token:
break
if not token:
raise AppException(
message="No available tokens. Please try again later.",
error_type=ErrorType.RATE_LIMIT.value,
code="rate_limit_exceeded",
status_code=429,
)
# 解析参数
think = {"enabled": True, "disabled": False}.get(thinking)
+1 -5
View File
@@ -646,7 +646,7 @@ class TokenManager:
# 重试逻辑:最多 2 次重试
for retry in range(3): # 0, 1, 2
try:
result = await usage_service.get(token_str)
result = await usage_service.get(token_str, model_name="grok-3")
if result and "remainingTokens" in result:
new_quota = result["remainingTokens"]
@@ -666,7 +666,6 @@ class TokenManager:
"expired": False,
}
token_info.mark_synced()
return {"recovered": False, "expired": False}
except Exception as e:
@@ -688,16 +687,13 @@ class TokenManager:
f"marking as expired"
)
token_info.status = TokenStatus.EXPIRED
token_info.mark_synced()
return {"recovered": False, "expired": True}
else:
logger.warning(
f"Token {token_info.token[:10]}...: refresh failed ({e})"
)
token_info.mark_synced()
return {"recovered": False, "expired": False}
token_info.mark_synced()
return {"recovered": False, "expired": False}
# 批量处理
+4 -1
View File
@@ -23,7 +23,6 @@ class TokenRefreshScheduler:
while self._running:
try:
await asyncio.sleep(self.interval_seconds)
storage = get_storage()
lock_acquired = False
lock = None
@@ -44,6 +43,7 @@ class TokenRefreshScheduler:
if not lock_acquired:
logger.info("Scheduler: skipped (lock not acquired)")
await asyncio.sleep(self.interval_seconds)
continue
try:
@@ -65,10 +65,13 @@ class TokenRefreshScheduler:
except Exception:
pass
await asyncio.sleep(self.interval_seconds)
except asyncio.CancelledError:
break
except Exception as e:
logger.error(f"Scheduler: refresh error - {e}")
await asyncio.sleep(self.interval_seconds)
def start(self):
"""启动调度器"""