From f1eab292a2681998d507b4f3aa15b0644dc6c274 Mon Sep 17 00:00:00 2001 From: gahusb Date: Fri, 20 Mar 2026 02:00:54 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=B1=EA=B3=BC=20=ED=86=B5=EA=B3=84=20?= =?UTF-8?q?=EC=9D=B8=EB=A9=94=EB=AA=A8=EB=A6=AC=20=EC=BA=90=EC=8B=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(GET=20/api/lotto/stats/performance)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 매 요청마다 전체 recommendations 조회하던 구조를 캐시로 개선. 갱신 시점: 새 회차 채점 직후(_sync_and_check) + TTL 1시간 만료 폴백 Co-Authored-By: Claude Sonnet 4.6 --- backend/app/main.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) 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) ────────────────────────────────────────────────