Add diskcache finctionality for caching sports api fixtures.
This commit is contained in:
@@ -14,7 +14,8 @@ dependencies = [
|
||||
"openpyxl>=3.1.0",
|
||||
"PyYaml==6.0.3",
|
||||
"playwright==1.58.0",
|
||||
"requests>=2.32.0"
|
||||
"requests>=2.32.0",
|
||||
"diskcache>=5.6",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
||||
@@ -5,3 +5,4 @@ from pydantic.dataclasses import dataclass
|
||||
class ResolverConfig:
|
||||
api_key: str
|
||||
league_map: dict[str, int]
|
||||
cache_path: str = "data/fixture_cache"
|
||||
|
||||
@@ -5,6 +5,7 @@ from difflib import SequenceMatcher
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
import diskcache
|
||||
import requests
|
||||
|
||||
from beaky import _ansi
|
||||
@@ -83,6 +84,7 @@ class TicketResolver:
|
||||
def __init__(self, config: ResolverConfig):
|
||||
self._headers = {"x-apisports-key": config.api_key}
|
||||
self._league_map = config.league_map
|
||||
self._disk_cache: diskcache.Cache = diskcache.Cache(config.cache_path)
|
||||
# Cache maps (center_date_str, league_id | None) -> list of fixture dicts
|
||||
self._fixture_cache: dict[tuple[str, int | None], list[dict[str, Any]]] = {}
|
||||
# Cache maps league name -> (league_id, confidence)
|
||||
@@ -150,19 +152,27 @@ class TicketResolver:
|
||||
cache_key = (date_str, league_id)
|
||||
|
||||
if cache_key not in self._fixture_cache:
|
||||
date_from = (center - timedelta(days=_DATE_WINDOW)).strftime("%Y-%m-%d")
|
||||
date_to = (center + timedelta(days=_DATE_WINDOW)).strftime("%Y-%m-%d")
|
||||
params: dict[str, str | int] = {"from": date_from, "to": date_to}
|
||||
if league_id is not None:
|
||||
params["league"] = league_id
|
||||
params["season"] = center.year if center.month >= 7 else center.year - 1
|
||||
print(_ansi.gray(f" │ GET /fixtures {params}"))
|
||||
resp = _get(f"{_API_BASE}/fixtures", headers=self._headers, params=params)
|
||||
resp.raise_for_status()
|
||||
self._fixture_cache[cache_key] = resp.json().get("response", [])
|
||||
print(_ansi.gray(f" │ {len(self._fixture_cache[cache_key])} fixtures returned (cached)"))
|
||||
if cache_key in self._disk_cache:
|
||||
self._fixture_cache[cache_key] = self._disk_cache[cache_key]
|
||||
print(_ansi.gray(f" │ /fixtures served from disk cache ({len(self._fixture_cache[cache_key])} fixtures)"))
|
||||
else:
|
||||
date_from = (center - timedelta(days=_DATE_WINDOW)).strftime("%Y-%m-%d")
|
||||
date_to = (center + timedelta(days=_DATE_WINDOW)).strftime("%Y-%m-%d")
|
||||
params: dict[str, str | int] = {"from": date_from, "to": date_to}
|
||||
if league_id is not None:
|
||||
params["league"] = league_id
|
||||
params["season"] = center.year if center.month >= 7 else center.year - 1
|
||||
print(_ansi.gray(f" │ GET /fixtures {params}"))
|
||||
resp = _get(f"{_API_BASE}/fixtures", headers=self._headers, params=params)
|
||||
resp.raise_for_status()
|
||||
self._fixture_cache[cache_key] = resp.json().get("response", [])
|
||||
print(_ansi.gray(f" │ {len(self._fixture_cache[cache_key])} fixtures returned"))
|
||||
finished = [f for f in self._fixture_cache[cache_key] if _is_finished(f) == 1.0]
|
||||
if finished:
|
||||
self._disk_cache[cache_key] = finished
|
||||
print(_ansi.gray(f" │ {len(finished)} finished fixture(s) written to disk cache"))
|
||||
else:
|
||||
print(_ansi.gray(f" │ /fixtures (±{_DATE_WINDOW}d of {date_str}, league={league_id}) served from cache"))
|
||||
print(_ansi.gray(f" │ /fixtures (±{_DATE_WINDOW}d of {date_str}, league={league_id}) served from memory"))
|
||||
|
||||
fixture, name_match, date_prox = _best_fixture_match(
|
||||
self._fixture_cache[cache_key], bet.team1Name, bet.team2Name, center
|
||||
|
||||
Reference in New Issue
Block a user