diff --git a/backend/app/main.py b/backend/app/main.py index 1017d4d..aa83c8c 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,4 +1,5 @@ import os +import time from typing import Optional, List, Dict, Any, Tuple from fastapi import FastAPI, HTTPException from pydantic import BaseModel @@ -42,6 +43,17 @@ scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul")) ALL_URL = os.getenv("LOTTO_ALL_URL", "https://smok95.github.io/lotto/results/all.json") LATEST_URL = os.getenv("LOTTO_LATEST_URL", "https://smok95.github.io/lotto/results/latest.json") +# ── 성과 통계 인메모리 캐시 ─────────────────────────────────────────────────── +# 채점 데이터는 하루 2번 스케줄러 실행 시에만 갱신되므로 인메모리 캐시로 충분 +_PERF_CACHE: Dict[str, Any] = {"data": None, "at": 0.0} +_PERF_CACHE_TTL = 3600 # 1시간 (스케줄러 미실행 상황 대비 폴백) + + +def _refresh_perf_cache() -> None: + _PERF_CACHE["data"] = get_recommendation_performance() + _PERF_CACHE["at"] = time.time() + print("[PerfCache] 성과 통계 캐시 갱신") + @app.on_event("startup") def on_startup(): @@ -53,6 +65,7 @@ def on_startup(): res = sync_latest(LATEST_URL) if res["was_new"]: check_results_for_draw(res["drawNo"]) + _refresh_perf_cache() # 새 채점 결과 반영 → 즉시 갱신 scheduler.add_job(_sync_and_check, "cron", hour="9,21", minute=10) @@ -170,15 +183,16 @@ def api_stats(): } -# ── 추천 성과 통계 (Phase 1) ───────────────────────────────────────────────── +# ── 추천 성과 통계 (Phase 1, 인메모리 캐시) ────────────────────────────────── @app.get("/api/lotto/stats/performance") def api_performance_stats(): """ - 채점된 추천 이력 기반 성과 통계. - - 평균 일치 개수, 분포, 등수별 현황 - - 무작위 대비 개선율 (이론 기댓값 0.8개 기준) + 채점된 추천 이력 기반 성과 통계 (캐시 반환). + 캐시 갱신 시점: 새 회차 채점 직후 | TTL 1시간 만료 시 """ - return get_recommendation_performance() + if _PERF_CACHE["data"] is None or time.time() - _PERF_CACHE["at"] > _PERF_CACHE_TTL: + _refresh_perf_cache() + return _PERF_CACHE["data"] # ── 회차 공략 리포트 (Phase 1) ────────────────────────────────────────────────