mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
fix: 修复限流状态判断逻辑,兼容对象和字符串格式
- 修复 cleanupOpenAIAccounts 方法中 rateLimitStatus 判断问题 - 修复 cleanupClaudeConsoleAccounts 方法中的判断逻辑 - 优化 unifiedOpenAIScheduler 的 _isRateLimited 辅助方法 - 保持原始服务层数据获取方式,通过判断逻辑适配不同数据格式 问题原因:服务层返回的 rateLimitStatus 是对象格式,但清理逻辑使用字符串比较, 导致限流账户无法被正确检测和自动恢复。 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -134,11 +134,18 @@ class RateLimitCleanupService {
|
|||||||
*/
|
*/
|
||||||
async cleanupOpenAIAccounts(result) {
|
async cleanupOpenAIAccounts(result) {
|
||||||
try {
|
try {
|
||||||
|
// 使用服务层获取账户数据
|
||||||
const accounts = await openaiAccountService.getAllAccounts()
|
const accounts = await openaiAccountService.getAllAccounts()
|
||||||
|
|
||||||
for (const account of accounts) {
|
for (const account of accounts) {
|
||||||
// 只检查标记为限流的账号
|
// 检查是否处于限流状态(兼容对象和字符串格式)
|
||||||
if (account.rateLimitStatus === 'limited') {
|
const isRateLimited =
|
||||||
|
account.rateLimitStatus === 'limited' ||
|
||||||
|
(account.rateLimitStatus &&
|
||||||
|
typeof account.rateLimitStatus === 'object' &&
|
||||||
|
account.rateLimitStatus.status === 'limited')
|
||||||
|
|
||||||
|
if (isRateLimited) {
|
||||||
result.checked++
|
result.checked++
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -180,17 +187,20 @@ class RateLimitCleanupService {
|
|||||||
*/
|
*/
|
||||||
async cleanupClaudeAccounts(result) {
|
async cleanupClaudeAccounts(result) {
|
||||||
try {
|
try {
|
||||||
// 使用原始数据而不是处理过的数据,避免字段被转换
|
// 使用 Redis 获取账户数据
|
||||||
const redis = require('../models/redis')
|
const redis = require('../models/redis')
|
||||||
const accounts = await redis.getAllClaudeAccounts()
|
const accounts = await redis.getAllClaudeAccounts()
|
||||||
|
|
||||||
for (const account of accounts) {
|
for (const account of accounts) {
|
||||||
// 检查所有可能处于限流状态的账号,包括自动停止的账号
|
// 检查是否处于限流状态(兼容对象和字符串格式)
|
||||||
if (
|
const isRateLimited =
|
||||||
account.rateLimitStatus === 'limited' ||
|
account.rateLimitStatus === 'limited' ||
|
||||||
account.rateLimitedAt ||
|
(account.rateLimitStatus &&
|
||||||
account.rateLimitAutoStopped === 'true'
|
typeof account.rateLimitStatus === 'object' &&
|
||||||
) {
|
account.rateLimitStatus.status === 'limited')
|
||||||
|
|
||||||
|
// 检查所有可能处于限流状态的账号,包括自动停止的账号
|
||||||
|
if (isRateLimited || account.rateLimitedAt || account.rateLimitAutoStopped === 'true') {
|
||||||
result.checked++
|
result.checked++
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -265,14 +275,21 @@ class RateLimitCleanupService {
|
|||||||
*/
|
*/
|
||||||
async cleanupClaudeConsoleAccounts(result) {
|
async cleanupClaudeConsoleAccounts(result) {
|
||||||
try {
|
try {
|
||||||
|
// 使用服务层获取账户数据
|
||||||
const accounts = await claudeConsoleAccountService.getAllAccounts()
|
const accounts = await claudeConsoleAccountService.getAllAccounts()
|
||||||
|
|
||||||
for (const account of accounts) {
|
for (const account of accounts) {
|
||||||
|
// 检查是否处于限流状态(兼容对象和字符串格式)
|
||||||
|
const isRateLimited =
|
||||||
|
account.rateLimitStatus === 'limited' ||
|
||||||
|
(account.rateLimitStatus &&
|
||||||
|
typeof account.rateLimitStatus === 'object' &&
|
||||||
|
account.rateLimitStatus.status === 'limited')
|
||||||
|
|
||||||
// 检查两种状态字段:rateLimitStatus 和 status
|
// 检查两种状态字段:rateLimitStatus 和 status
|
||||||
const hasRateLimitStatus = account.rateLimitStatus === 'limited'
|
|
||||||
const hasStatusRateLimited = account.status === 'rate_limited'
|
const hasStatusRateLimited = account.status === 'rate_limited'
|
||||||
|
|
||||||
if (hasRateLimitStatus || hasStatusRateLimited) {
|
if (isRateLimited || hasStatusRateLimited) {
|
||||||
result.checked++
|
result.checked++
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -285,7 +302,7 @@ class RateLimitCleanupService {
|
|||||||
result.cleared++
|
result.cleared++
|
||||||
|
|
||||||
// 如果 status 字段是 rate_limited,需要额外清理
|
// 如果 status 字段是 rate_limited,需要额外清理
|
||||||
if (hasStatusRateLimited && !hasRateLimitStatus) {
|
if (hasStatusRateLimited && !isRateLimited) {
|
||||||
await claudeConsoleAccountService.updateAccount(account.id, {
|
await claudeConsoleAccountService.updateAccount(account.id, {
|
||||||
status: 'active'
|
status: 'active'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,6 +19,26 @@ class UnifiedOpenAIScheduler {
|
|||||||
return schedulable !== false && schedulable !== 'false'
|
return schedulable !== false && schedulable !== 'false'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🔧 辅助方法:检查账户是否被限流(兼容字符串和对象格式)
|
||||||
|
_isRateLimited(rateLimitStatus) {
|
||||||
|
if (!rateLimitStatus) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容字符串格式(Redis 原始数据)
|
||||||
|
if (typeof rateLimitStatus === 'string') {
|
||||||
|
return rateLimitStatus === 'limited'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容对象格式(getAllAccounts 返回的数据)
|
||||||
|
if (typeof rateLimitStatus === 'object') {
|
||||||
|
// 检查对象中的 status 字段
|
||||||
|
return rateLimitStatus.status === 'limited' || rateLimitStatus.isRateLimited === true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 🎯 统一调度OpenAI账号
|
// 🎯 统一调度OpenAI账号
|
||||||
async selectAccountForApiKey(apiKeyData, sessionHash = null, requestedModel = null) {
|
async selectAccountForApiKey(apiKeyData, sessionHash = null, requestedModel = null) {
|
||||||
try {
|
try {
|
||||||
@@ -63,7 +83,7 @@ class UnifiedOpenAIScheduler {
|
|||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
accountType === 'openai-responses' &&
|
accountType === 'openai-responses' &&
|
||||||
boundAccount.rateLimitStatus === 'limited'
|
this._isRateLimited(boundAccount.rateLimitStatus)
|
||||||
) {
|
) {
|
||||||
// OpenAI-Responses 账户的限流检查
|
// OpenAI-Responses 账户的限流检查
|
||||||
const isRateLimitCleared = await openaiResponsesAccountService.checkAndClearRateLimit(
|
const isRateLimitCleared = await openaiResponsesAccountService.checkAndClearRateLimit(
|
||||||
@@ -283,7 +303,7 @@ class UnifiedOpenAIScheduler {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 如果仍然处于限流状态,跳过
|
// 如果仍然处于限流状态,跳过
|
||||||
if (account.rateLimitStatus === 'limited' && !isRateLimitCleared) {
|
if (this._isRateLimited(account.rateLimitStatus) && !isRateLimitCleared) {
|
||||||
logger.debug(`⏭️ Skipping OpenAI-Responses account ${account.name} - rate limited`)
|
logger.debug(`⏭️ Skipping OpenAI-Responses account ${account.name} - rate limited`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -350,7 +370,7 @@ class UnifiedOpenAIScheduler {
|
|||||||
// 检查并清除过期的限流状态
|
// 检查并清除过期的限流状态
|
||||||
const isRateLimitCleared =
|
const isRateLimitCleared =
|
||||||
await openaiResponsesAccountService.checkAndClearRateLimit(accountId)
|
await openaiResponsesAccountService.checkAndClearRateLimit(accountId)
|
||||||
return account.rateLimitStatus !== 'limited' || isRateLimitCleared
|
return !this._isRateLimited(account.rateLimitStatus) || isRateLimitCleared
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -504,7 +524,7 @@ class UnifiedOpenAIScheduler {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.rateLimitStatus === 'limited') {
|
if (this._isRateLimited(account.rateLimitStatus)) {
|
||||||
// 如果有具体的重置时间,使用它
|
// 如果有具体的重置时间,使用它
|
||||||
if (account.rateLimitResetAt) {
|
if (account.rateLimitResetAt) {
|
||||||
const resetTime = new Date(account.rateLimitResetAt).getTime()
|
const resetTime = new Date(account.rateLimitResetAt).getTime()
|
||||||
|
|||||||
Reference in New Issue
Block a user