perf: persistance du cache concerts en SQLite (survit aux redémarrages)
Docker / docker (push) Successful in 3m31s
Docker / docker (push) Successful in 3m31s
Le cache en mémoire (6h TTL) est désormais sauvegardé dans concerts_cache. Au redémarrage, si le cache SQLite est récent, aucune requête réseau n'est faite. Le bouton Rafraîchir vide aussi le cache SQLite pour forcer un re-scrape. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+59
@@ -1,4 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -11,8 +12,51 @@ import tmdb as _tmdb
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
CACHE_TTL = 6 * 3600
|
CACHE_TTL = 6 * 3600
|
||||||
|
DB_PATH = "arte_dl.db"
|
||||||
_cache: dict = {"data": [], "ts": 0}
|
_cache: dict = {"data": [], "ts": 0}
|
||||||
|
|
||||||
|
|
||||||
|
def _db():
|
||||||
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def _init_concerts_cache_table():
|
||||||
|
with _db() as conn:
|
||||||
|
conn.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS concerts_cache (
|
||||||
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||||
|
data TEXT NOT NULL,
|
||||||
|
ts REAL NOT NULL
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
_init_concerts_cache_table()
|
||||||
|
|
||||||
|
|
||||||
|
def _load_db_cache() -> tuple[list, float]:
|
||||||
|
try:
|
||||||
|
with _db() as conn:
|
||||||
|
row = conn.execute("SELECT data, ts FROM concerts_cache WHERE id=1").fetchone()
|
||||||
|
if row:
|
||||||
|
return json.loads(row["data"]), row["ts"]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return [], 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def _save_db_cache(data: list, ts: float):
|
||||||
|
try:
|
||||||
|
with _db() as conn:
|
||||||
|
conn.execute(
|
||||||
|
"INSERT OR REPLACE INTO concerts_cache (id, data, ts) VALUES (1, ?, ?)",
|
||||||
|
(json.dumps(data), ts),
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Failed to save concerts cache: %s", e)
|
||||||
|
|
||||||
PLAYER_API = "https://api.arte.tv/api/player/v2/config/fr/{pid}"
|
PLAYER_API = "https://api.arte.tv/api/player/v2/config/fr/{pid}"
|
||||||
SEARCH_URL = "https://www.arte.tv/fr/search/?q={q}"
|
SEARCH_URL = "https://www.arte.tv/fr/search/?q={q}"
|
||||||
|
|
||||||
@@ -157,11 +201,21 @@ async def get_all_concerts() -> list[dict]:
|
|||||||
now = time.time()
|
now = time.time()
|
||||||
if _cache["data"] and now - _cache["ts"] < CACHE_TTL:
|
if _cache["data"] and now - _cache["ts"] < CACHE_TTL:
|
||||||
return _cache["data"]
|
return _cache["data"]
|
||||||
|
|
||||||
|
# Try SQLite cache before hitting the network
|
||||||
|
db_data, db_ts = _load_db_cache()
|
||||||
|
if db_data and now - db_ts < CACHE_TTL:
|
||||||
|
logger.info("Concerts cache loaded from DB (%d concerts)", len(db_data))
|
||||||
|
_cache["data"] = db_data
|
||||||
|
_cache["ts"] = db_ts
|
||||||
|
return _cache["data"]
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
data = await loop.run_in_executor(None, _fetch_all_sync)
|
data = await loop.run_in_executor(None, _fetch_all_sync)
|
||||||
if data:
|
if data:
|
||||||
_cache["data"] = data
|
_cache["data"] = data
|
||||||
_cache["ts"] = now
|
_cache["ts"] = now
|
||||||
|
_save_db_cache(data, now)
|
||||||
return _cache["data"]
|
return _cache["data"]
|
||||||
|
|
||||||
|
|
||||||
@@ -208,5 +262,10 @@ async def fetch_concerts(page: int = 1, search: str = "", page_size: int = 24, c
|
|||||||
|
|
||||||
async def invalidate_cache() -> int:
|
async def invalidate_cache() -> int:
|
||||||
_cache["ts"] = 0
|
_cache["ts"] = 0
|
||||||
|
try:
|
||||||
|
with _db() as conn:
|
||||||
|
conn.execute("DELETE FROM concerts_cache")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
data = await get_all_concerts()
|
data = await get_all_concerts()
|
||||||
return len(data)
|
return len(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user