feat: bzzoiro 多 API Key 轮换,遇限流自动切换
新增 KeyRing 轮换环(src/data/key_ring.py): - 支持逗号/分号/换行分隔多个 key,单 key 场景零开销 - 遇到 429 自动标记当前 key 冷却(默认 60s)并立即切换到下一个 key - 全部 key 冷却时等待最早恢复的 key,避免无谓重试 - 热更新 key 列表(增删 key 无需重启) - 进程级单例,按 base URL 隔离 后端集成: - bzzoiro._fetch_json_async 接入 KeyRing,429 立即轮换(不等待) - 新增 /admin/keyring/status 端点展示 key 环状态 - 新增 /admin/keyring/cooldown/reset 紧急重置冷却 - BZZOIRO_KEY 配置描述提示多 key 支持 - mask_value 多 key 显示数量(如 "3 个 key(末段 …XXXX)") - 清理已移除 injuries 的 API_FOOTBALL_KEY 配置项 前端: - 数据源页新增 Key Ring 状态面板(每个 key 可用/冷却状态 + 重置按钮) - 配置项脱敏展示支持多 key 计数 测试: 新增 24 个 KeyRing 单元测试 + 2 个 bzzoiro 轮换集成测试,全部通过。 Co-Authored-By: new-provider/LongCat-2.0 <<EMAIL>>
This commit is contained in:
co-authored by
new-provider/LongCat-2.0 <
parent
f05dc1ae15
commit
f52ec8b963
@@ -31,7 +31,6 @@ class Settings(BaseSettings):
|
||||
# --- data sources ---
|
||||
BZZOIRO_KEY: str = ""
|
||||
BZZOIRO_BASE: str = "https://sports.bzzoiro.com/api/v2"
|
||||
API_FOOTBALL_KEY: str = ""
|
||||
|
||||
# --- 代理头信任 ---
|
||||
# 为 True 时才解析 X-Forwarded-For,否则只用 request.client.host。
|
||||
|
||||
@@ -7,6 +7,7 @@ DB 读取失败时也回落环境变量,保证采集不因管理表故障而中
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
import secrets
|
||||
from dataclasses import dataclass
|
||||
|
||||
@@ -39,14 +40,13 @@ class SettingDef:
|
||||
# 允许在后台查看/修改的配置项白名单(之外的 key 一律拒绝读写)
|
||||
SETTING_DEFS: dict[str, SettingDef] = {
|
||||
"BZZOIRO_KEY": SettingDef(
|
||||
"BZZOIRO_KEY", "Bzzoiro API Key", "比赛赛程 / 比分数据源凭证", sensitive=True,
|
||||
"BZZOIRO_KEY", "Bzzoiro API Key",
|
||||
"比赛赛程/比分/积分榜/统计的数据源凭证。支持多 key 轮换:用逗号、分号或换行分隔多个 key,遇到限流(429)自动切换",
|
||||
sensitive=True,
|
||||
),
|
||||
"BZZOIRO_BASE": SettingDef(
|
||||
"BZZOIRO_BASE", "Bzzoiro API 地址", "Bzzoiro 接口基础地址", sensitive=False,
|
||||
),
|
||||
"API_FOOTBALL_KEY": SettingDef(
|
||||
"API_FOOTBALL_KEY", "API-Football Key", "伤停数据源凭证(api-sports)", sensitive=True,
|
||||
),
|
||||
"LLM_API_KEY": SettingDef(
|
||||
"LLM_API_KEY", "LLM API Key", "大模型服务凭证(OpenAI 兼容接口)", sensitive=True,
|
||||
),
|
||||
@@ -83,11 +83,20 @@ for _agent in AGENT_META:
|
||||
|
||||
|
||||
def mask_value(value: str, sensitive: bool) -> str:
|
||||
"""脱敏展示:敏感值只留末 4 位;非敏感值原样返回。"""
|
||||
"""脱敏展示:敏感值只留末 4 位;非敏感值原样返回。
|
||||
|
||||
多 key(逗号/分号/换行分隔)时显示数量,如 "3 个 key(末段 …XXXX)"。
|
||||
"""
|
||||
if not value:
|
||||
return ""
|
||||
if not sensitive:
|
||||
return value
|
||||
# 检测多 key
|
||||
keys = [k.strip() for k in re.split(r"[,;\n]", value) if k.strip()]
|
||||
if len(keys) > 1:
|
||||
last = keys[-1]
|
||||
tail = last[-4:] if len(last) >= 4 else last
|
||||
return f"{len(keys)} 个 key(末段 …{tail})"
|
||||
return f"****{value[-4:]}" if len(value) >= 8 else "****"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user