定时任务:更新失败的API密钥缓存
()
| 79 | # ==================== 定时任务函数 ==================== |
| 80 | |
| 81 | def update_failed_keys_cache(): |
| 82 | """定时任务:更新失败的API密钥缓存""" |
| 83 | global last_update_time |
| 84 | start_time = datetime.now() |
| 85 | logger.info("🔄 开始更新失败API密钥缓存...") |
| 86 | |
| 87 | try: |
| 88 | # 获取数据库会话 |
| 89 | db = next(get_db()) |
| 90 | |
| 91 | # 计算时间窗口 |
| 92 | cutoff_time = datetime.now() - timedelta(minutes=TOLERANCE_TIMER_SPAN) |
| 93 | |
| 94 | # 重置缓存 |
| 95 | failed_keys_cache.clear() |
| 96 | key_failure_count_cache.clear() |
| 97 | stats_cache.clear() |
| 98 | |
| 99 | # 批量查询所有失败的API密钥 - 使用优化的索引查询 |
| 100 | failed_keys_query = db.query( |
| 101 | ApiKeyUsage.source_name, |
| 102 | ApiKeyUsage.api_key, |
| 103 | func.count(ApiKeyUsage.request_id).label('failure_count'), |
| 104 | func.max(ApiKeyUsage.finish_time).label('last_failure') |
| 105 | ).filter( |
| 106 | and_( |
| 107 | ApiKeyUsage.status == False, |
| 108 | ApiKeyUsage.finish_time >= cutoff_time |
| 109 | ) |
| 110 | ).group_by( |
| 111 | ApiKeyUsage.source_name, |
| 112 | ApiKeyUsage.api_key |
| 113 | ).all() |
| 114 | |
| 115 | # 统计信息 |
| 116 | total_failed_keys = 0 |
| 117 | source_stats = defaultdict(lambda: { |
| 118 | 'failed_keys': 0, |
| 119 | 'total_failures': 0, |
| 120 | 'models_affected': set(), |
| 121 | 'last_failure': None |
| 122 | }) |
| 123 | |
| 124 | # 处理查询结果 |
| 125 | for row in failed_keys_query: |
| 126 | source_name = row.source_name |
| 127 | api_key = row.api_key |
| 128 | failure_count = row.failure_count |
| 129 | last_failure = row.last_failure |
| 130 | |
| 131 | # 添加到失败缓存 |
| 132 | failed_keys_cache[source_name].add(api_key) |
| 133 | # 记录失败次数 |
| 134 | key_failure_count_cache[source_name][api_key] = failure_count |
| 135 | total_failed_keys += 1 |
| 136 | |
| 137 | # 更新统计信息 |
| 138 | source_stats[source_name]['failed_keys'] += 1 |
no test coverage detected