From b4233033a6d7de9d5dd198ff4aadca9d6abbfb36 Mon Sep 17 00:00:00 2001 From: SunSeekerX Date: Wed, 31 Dec 2025 02:17:10 +0800 Subject: [PATCH] chore --- scripts/migrate-usage-index.js | 8 +++++++- src/routes/admin/apiKeys.js | 8 ++------ src/services/claudeCodeHeadersService.js | 6 +++++- src/services/claudeRelayService.js | 4 +--- src/services/costInitService.js | 4 +++- src/services/droidAccountService.js | 11 +++++++---- src/services/droidScheduler.js | 7 ++++++- src/services/unifiedGeminiScheduler.js | 24 ++++-------------------- src/utils/commonHelper.js | 20 +++++++++++++++----- 9 files changed, 50 insertions(+), 42 deletions(-) diff --git a/scripts/migrate-usage-index.js b/scripts/migrate-usage-index.js index 77c2db0c..ca4f42c4 100644 --- a/scripts/migrate-usage-index.js +++ b/scripts/migrate-usage-index.js @@ -93,7 +93,13 @@ async function migrate() { console.log('\n4. 迁移 usage:model:hourly 索引...') cursor = '0' do { - const [newCursor, keys] = await redis.scan(cursor, 'MATCH', 'usage:model:hourly:*', 'COUNT', 500) + const [newCursor, keys] = await redis.scan( + cursor, + 'MATCH', + 'usage:model:hourly:*', + 'COUNT', + 500 + ) cursor = newCursor const pipeline = redis.pipeline() diff --git a/src/routes/admin/apiKeys.js b/src/routes/admin/apiKeys.js index 4a74cfda..5a92937a 100644 --- a/src/routes/admin/apiKeys.js +++ b/src/routes/admin/apiKeys.js @@ -289,17 +289,13 @@ router.get('/api-keys', authenticateAdmin, async (req, res) => { } // 为每个API Key添加owner的displayName(批量获取优化) - const userIdsToFetch = [ - ...new Set(result.items.filter((k) => k.userId).map((k) => k.userId)) - ] + const userIdsToFetch = [...new Set(result.items.filter((k) => k.userId).map((k) => k.userId))] const userMap = new Map() if (userIdsToFetch.length > 0) { // 批量获取用户信息 const users = await Promise.all( - userIdsToFetch.map((id) => - userService.getUserById(id, false).catch(() => null) - ) + userIdsToFetch.map((id) => userService.getUserById(id, false).catch(() => null)) ) userIdsToFetch.forEach((id, i) => { if (users[i]) userMap.set(id, users[i]) diff --git a/src/services/claudeCodeHeadersService.js b/src/services/claudeCodeHeadersService.js index 8a8b48fb..4c016494 100644 --- a/src/services/claudeCodeHeadersService.js +++ b/src/services/claudeCodeHeadersService.js @@ -5,7 +5,11 @@ const redis = require('../models/redis') const logger = require('../utils/logger') -const { getCachedConfig, setCachedConfig, deleteCachedConfig } = require('../utils/performanceOptimizer') +const { + getCachedConfig, + setCachedConfig, + deleteCachedConfig +} = require('../utils/performanceOptimizer') class ClaudeCodeHeadersService { constructor() { diff --git a/src/services/claudeRelayService.js b/src/services/claudeRelayService.js index 9f02af1c..95da1c7a 100644 --- a/src/services/claudeRelayService.js +++ b/src/services/claudeRelayService.js @@ -24,9 +24,7 @@ const { // structuredClone polyfill for Node < 17 const safeClone = - typeof structuredClone === 'function' - ? structuredClone - : (obj) => JSON.parse(JSON.stringify(obj)) + typeof structuredClone === 'function' ? structuredClone : (obj) => JSON.parse(JSON.stringify(obj)) class ClaudeRelayService { constructor() { diff --git a/src/services/costInitService.js b/src/services/costInitService.js index c0b55850..6dfc684d 100644 --- a/src/services/costInitService.js +++ b/src/services/costInitService.js @@ -94,7 +94,9 @@ class CostInitService { } } - logger.info(`💰 Found ${apiKeyIds.length} active API Keys to process (filtered ${allKeyIds.length - apiKeyIds.length} deleted)`) + logger.info( + `💰 Found ${apiKeyIds.length} active API Keys to process (filtered ${allKeyIds.length - apiKeyIds.length} deleted)` + ) let processedCount = 0 let errorCount = 0 diff --git a/src/services/droidAccountService.js b/src/services/droidAccountService.js index b8669231..01e6fd91 100644 --- a/src/services/droidAccountService.js +++ b/src/services/droidAccountService.js @@ -30,10 +30,13 @@ class DroidAccountService { this._encryptor = createEncryptor('droid-account-salt') // 🧹 定期清理缓存(每10分钟) - setInterval(() => { - this._encryptor.clearCache() - logger.info('🧹 Droid decrypt cache cleanup completed', this._encryptor.getStats()) - }, 10 * 60 * 1000) + setInterval( + () => { + this._encryptor.clearCache() + logger.info('🧹 Droid decrypt cache cleanup completed', this._encryptor.getStats()) + }, + 10 * 60 * 1000 + ) this.supportedEndpointTypes = new Set(['anthropic', 'openai', 'comm']) } diff --git a/src/services/droidScheduler.js b/src/services/droidScheduler.js index 37ea9e4b..ed83d7a9 100644 --- a/src/services/droidScheduler.js +++ b/src/services/droidScheduler.js @@ -2,7 +2,12 @@ const droidAccountService = require('./droidAccountService') const accountGroupService = require('./accountGroupService') const redis = require('../models/redis') const logger = require('../utils/logger') -const { isTruthy, isAccountHealthy, sortAccountsByPriority, normalizeEndpointType } = require('../utils/commonHelper') +const { + isTruthy, + isAccountHealthy, + sortAccountsByPriority, + normalizeEndpointType +} = require('../utils/commonHelper') class DroidScheduler { constructor() { diff --git a/src/services/unifiedGeminiScheduler.js b/src/services/unifiedGeminiScheduler.js index 2581196b..381ff51a 100644 --- a/src/services/unifiedGeminiScheduler.js +++ b/src/services/unifiedGeminiScheduler.js @@ -26,11 +26,7 @@ class UnifiedGeminiScheduler { if (apiKeyData.geminiAccountId.startsWith('api:')) { const accountId = apiKeyData.geminiAccountId.replace('api:', '') const boundAccount = await geminiApiAccountService.getAccount(accountId) - if ( - boundAccount && - isActive(boundAccount.isActive) && - boundAccount.status !== 'error' - ) { + if (boundAccount && isActive(boundAccount.isActive) && boundAccount.status !== 'error') { logger.info( `🎯 Using bound Gemini-API account: ${boundAccount.name} (${accountId}) for API key ${apiKeyData.name}` ) @@ -63,11 +59,7 @@ class UnifiedGeminiScheduler { // 普通 Gemini OAuth 专属账户 else { const boundAccount = await geminiAccountService.getAccount(apiKeyData.geminiAccountId) - if ( - boundAccount && - isActive(boundAccount.isActive) && - boundAccount.status !== 'error' - ) { + if (boundAccount && isActive(boundAccount.isActive) && boundAccount.status !== 'error') { logger.info( `🎯 Using bound dedicated Gemini account: ${boundAccount.name} (${apiKeyData.geminiAccountId}) for API key ${apiKeyData.name}` ) @@ -183,11 +175,7 @@ class UnifiedGeminiScheduler { if (apiKeyData.geminiAccountId.startsWith('api:')) { const accountId = apiKeyData.geminiAccountId.replace('api:', '') const boundAccount = await geminiApiAccountService.getAccount(accountId) - if ( - boundAccount && - isActive(boundAccount.isActive) && - boundAccount.status !== 'error' - ) { + if (boundAccount && isActive(boundAccount.isActive) && boundAccount.status !== 'error') { const isRateLimited = await this.isAccountRateLimited(accountId) if (!isRateLimited) { // 检查模型支持 @@ -234,11 +222,7 @@ class UnifiedGeminiScheduler { // 普通 Gemini OAuth 账户 else if (!apiKeyData.geminiAccountId.startsWith('group:')) { const boundAccount = await geminiAccountService.getAccount(apiKeyData.geminiAccountId) - if ( - boundAccount && - isActive(boundAccount.isActive) && - boundAccount.status !== 'error' - ) { + if (boundAccount && isActive(boundAccount.isActive) && boundAccount.status !== 'error') { const isRateLimited = await this.isAccountRateLimited(boundAccount.id) if (!isRateLimited) { // 检查模型支持 diff --git a/src/utils/commonHelper.js b/src/utils/commonHelper.js index 752166da..2615082f 100644 --- a/src/utils/commonHelper.js +++ b/src/utils/commonHelper.js @@ -84,7 +84,10 @@ const getDecryptCacheStats = defaultEncryptor.getStats // ============================================ // 转换为布尔值(宽松模式) -const toBoolean = (value) => value === true || value === 'true' || (typeof value === 'string' && value.toLowerCase() === 'true') +const toBoolean = (value) => + value === true || + value === 'true' || + (typeof value === 'string' && value.toLowerCase() === 'true') // 检查是否为真值(null/undefined 返回 false) const isTruthy = (value) => value != null && toBoolean(value) @@ -110,7 +113,11 @@ const isAccountHealthy = (account) => { // 安全解析 JSON const safeParseJson = (value, fallback = null) => { if (!value || typeof value !== 'string') return fallback - try { return JSON.parse(value) } catch { return fallback } + try { + return JSON.parse(value) + } catch { + return fallback + } } // 安全解析 JSON 为对象 @@ -134,7 +141,10 @@ const normalizeModelName = (model) => { if (!model || model === 'unknown') return model // Bedrock 模型: us-east-1.anthropic.claude-3-5-sonnet-v1:0 if (model.includes('.anthropic.') || model.includes('.claude')) { - return model.replace(/^[a-z0-9-]+\./, '').replace('anthropic.', '').replace(/-v\d+:\d+$/, '') + return model + .replace(/^[a-z0-9-]+\./, '') + .replace('anthropic.', '') + .replace(/-v\d+:\d+$/, '') } return model.replace(/-v\d+:\d+$|:latest$/, '') } @@ -151,7 +161,7 @@ const isModelInMapping = (modelMapping, requestedModel) => { if (!modelMapping || Object.keys(modelMapping).length === 0) return true if (Object.prototype.hasOwnProperty.call(modelMapping, requestedModel)) return true const lower = requestedModel.toLowerCase() - return Object.keys(modelMapping).some(k => k.toLowerCase() === lower) + return Object.keys(modelMapping).some((k) => k.toLowerCase() === lower) } // 获取映射后的模型名称 @@ -192,7 +202,7 @@ const composeStickySessionKey = (prefix, sessionHash, apiKeyId = null) => { // 过滤可用账户(激活 + 健康 + 可调度) const filterAvailableAccounts = (accounts) => { - return accounts.filter(acc => acc && isAccountHealthy(acc) && isSchedulable(acc.schedulable)) + return accounts.filter((acc) => acc && isAccountHealthy(acc) && isSchedulable(acc.schedulable)) } // ============================================