refactor: fix P0/P1/P2 security and performance issues

P0 fixes:
- CORS: replace wildcard methods/headers with configurable lists
- deps.py: remove unsafe global _warned_unset variable

P1 fixes:
- http_client: read default timeout from Settings
- bzzoiro: replace sync urllib with async httpx
- bzzoiro: normalize validation failures use warning level only
- db pool: read pool config from Settings (default 5+10)
- backtest: add asyncio.Semaphore(8) for concurrent execution
- predict/context_builder: add backtest parameter for cutoff buffer

P2 improvements:
- injuries: enforce int conversion for player_id/fixture_id
- injuries: use system temp dir for cache
- utils.py: extract shared actual_1x2/is_correct_1x2
- validation: downgrade 1x2 mismatch log to debug
- docker-compose: use env vars for all credentials
- .env.example: add POSTGRES_USER/PASSWORD/PORT, API_PORT
This commit is contained in:
shangfangjian
2026-09-16 02:38:25 +08:00
parent fa69795d69
commit 983b620659
14 changed files with 154 additions and 109 deletions
+12 -2
View File
@@ -8,6 +8,7 @@ import asyncio
import json
import logging
import random
import tempfile
import time
from datetime import datetime, timezone
from pathlib import Path
@@ -23,8 +24,8 @@ logger = logging.getLogger(__name__)
API_BASE = "https://v3.football.api-sports.io"
DEFAULT_HOST = "v3.football.api-sports.io"
# 缓存目录
_CACHE_DIR = Path(__file__).resolve().parent.parent.parent / "data" / "injuries_cache"
# P2-3: 缓存目录改用系统临时目录,避免源码树内写入
_CACHE_DIR = Path(tempfile.gettempdir()) / "profeto_injuries"
async def fetch_injuries(*, date: str | None = None, fixture_id: int | None = None, league_id: int | None = None) -> list[dict]:
@@ -144,8 +145,17 @@ async def ingest_injuries(db, *, date: str | None = None) -> dict:
except (ValueError, AttributeError):
pass
# P2-1: 强制 int 转换,API 可能返回字符串
player_id = player.get("id")
try:
player_id = int(player_id) if player_id is not None else None
except (ValueError, TypeError):
player_id = None
fixture_id = fixture.get("id")
try:
fixture_id = int(fixture_id) if fixture_id is not None else None
except (ValueError, TypeError):
fixture_id = None
# 幂等: 已存在则跳过
existing = (