fix: 修复5小时限制被停止调度未恢复的问题

This commit is contained in:
shaw
2025-09-28 23:30:41 +08:00
parent aca2b1cccb
commit b4d7ed06c5

View File

@@ -599,6 +599,7 @@ class ClaudeAccountService {
'unifiedClientId' 'unifiedClientId'
] ]
const updatedData = { ...accountData } const updatedData = { ...accountData }
let shouldClearAutoStopFields = false
// 检查是否新增了 refresh token // 检查是否新增了 refresh token
const oldRefreshToken = this._decryptSensitiveData(accountData.refreshToken) const oldRefreshToken = this._decryptSensitiveData(accountData.refreshToken)
@@ -669,6 +670,7 @@ class ClaudeAccountService {
// 兼容旧的标记(逐步迁移) // 兼容旧的标记(逐步迁移)
delete updatedData.autoStoppedAt delete updatedData.autoStoppedAt
delete updatedData.stoppedReason delete updatedData.stoppedReason
shouldClearAutoStopFields = true
// 如果是手动启用调度,记录日志 // 如果是手动启用调度,记录日志
if (updates.schedulable === true || updates.schedulable === 'true') { if (updates.schedulable === true || updates.schedulable === 'true') {
@@ -700,6 +702,18 @@ class ClaudeAccountService {
await redis.setClaudeAccount(accountId, updatedData) await redis.setClaudeAccount(accountId, updatedData)
if (shouldClearAutoStopFields) {
const fieldsToRemove = [
'rateLimitAutoStopped',
'fiveHourAutoStopped',
'fiveHourStoppedAt',
'tempErrorAutoStopped',
'autoStoppedAt',
'stoppedReason'
]
await this._removeAccountFields(accountId, fieldsToRemove, 'manual_schedule_update')
}
logger.success(`📝 Updated Claude account: ${accountId}`) logger.success(`📝 Updated Claude account: ${accountId}`)
return { success: true } return { success: true }
@@ -1399,6 +1413,9 @@ class ClaudeAccountService {
const now = new Date() const now = new Date()
const currentTime = now.getTime() const currentTime = now.getTime()
let shouldClearSessionStatus = false
let shouldClearFiveHourFlags = false
// 检查当前是否有活跃的会话窗口 // 检查当前是否有活跃的会话窗口
if (accountData.sessionWindowStart && accountData.sessionWindowEnd) { if (accountData.sessionWindowStart && accountData.sessionWindowEnd) {
const windowEnd = new Date(accountData.sessionWindowEnd).getTime() const windowEnd = new Date(accountData.sessionWindowEnd).getTime()
@@ -1429,6 +1446,7 @@ class ClaudeAccountService {
if (accountData.sessionWindowStatus) { if (accountData.sessionWindowStatus) {
delete accountData.sessionWindowStatus delete accountData.sessionWindowStatus
delete accountData.sessionWindowStatusUpdatedAt delete accountData.sessionWindowStatusUpdatedAt
shouldClearSessionStatus = true
} }
// 如果账户因为5小时限制被自动停止现在恢复调度 // 如果账户因为5小时限制被自动停止现在恢复调度
@@ -1439,6 +1457,7 @@ class ClaudeAccountService {
accountData.schedulable = 'true' accountData.schedulable = 'true'
delete accountData.fiveHourAutoStopped delete accountData.fiveHourAutoStopped
delete accountData.fiveHourStoppedAt delete accountData.fiveHourStoppedAt
shouldClearFiveHourFlags = true
// 发送Webhook通知 // 发送Webhook通知
try { try {
@@ -1457,6 +1476,17 @@ class ClaudeAccountService {
} }
} }
if (shouldClearSessionStatus || shouldClearFiveHourFlags) {
const fieldsToRemove = []
if (shouldClearFiveHourFlags) {
fieldsToRemove.push('fiveHourAutoStopped', 'fiveHourStoppedAt')
}
if (shouldClearSessionStatus) {
fieldsToRemove.push('sessionWindowStatus', 'sessionWindowStatusUpdatedAt')
}
await this._removeAccountFields(accountId, fieldsToRemove, 'session_window_refresh')
}
logger.info( logger.info(
`🕐 Created new session window for account ${accountData.name} (${accountId}): ${windowStart.toISOString()} - ${windowEnd.toISOString()} (from current time)` `🕐 Created new session window for account ${accountData.name} (${accountId}): ${windowStart.toISOString()} - ${windowEnd.toISOString()} (from current time)`
) )
@@ -2486,6 +2516,12 @@ class ClaudeAccountService {
// 保存更新 // 保存更新
await redis.setClaudeAccount(account.id, updatedAccountData) await redis.setClaudeAccount(account.id, updatedAccountData)
const fieldsToRemove = ['fiveHourAutoStopped', 'fiveHourStoppedAt']
if (newWindowStart && newWindowEnd) {
fieldsToRemove.push('sessionWindowStatus', 'sessionWindowStatusUpdatedAt')
}
await this._removeAccountFields(account.id, fieldsToRemove, 'five_hour_recovery_task')
result.recovered++ result.recovered++
result.accounts.push({ result.accounts.push({
id: latestAccount.id, id: latestAccount.id,
@@ -2541,6 +2577,31 @@ class ClaudeAccountService {
throw error throw error
} }
} }
async _removeAccountFields(accountId, fields = [], context = 'general_cleanup') {
if (!Array.isArray(fields) || fields.length === 0) {
return
}
const filteredFields = fields.filter((field) => typeof field === 'string' && field.trim())
if (filteredFields.length === 0) {
return
}
const accountKey = `claude:account:${accountId}`
try {
await redis.client.hdel(accountKey, ...filteredFields)
logger.debug(
`🧹 已在 ${context} 阶段为账号 ${accountId} 删除字段 [${filteredFields.join(', ')}]`
)
} catch (error) {
logger.error(
`❌ 无法在 ${context} 阶段为账号 ${accountId} 删除字段 [${filteredFields.join(', ')}]:`,
error
)
}
}
} }
module.exports = new ClaudeAccountService() module.exports = new ClaudeAccountService()