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