Skip to content

Commit 25072f2

Browse files
authored
Change: cache wall API responses until state (#231)
* Change: Cache wall API responses * Change: version to v0.9.18
1 parent 5fafb32 commit 25072f2

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

api/versionAPI.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
router = APIRouter(prefix="/api", tags=["version"])
2121

22-
CURRENT_VERSION = os.getenv("APP_VERSION", "v0.9.17")
22+
CURRENT_VERSION = os.getenv("APP_VERSION", "v0.9.18")
2323
REPO = os.getenv("GITHUB_REPO", "cenodude/CrossWatch")
2424

2525

api/wallAPI.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,37 @@
33
# Copyright (c) 2025-2026 CrossWatch / Cenodude (https://github.com/cenodude/CrossWatch)
44
from __future__ import annotations
55

6+
import threading
67
from typing import Any
78
from fastapi import FastAPI, Query
89

9-
from cw_platform.config_base import load_config
10+
from cw_platform.config_base import config_path, load_config
1011
from services.watchlist import build_watchlist, detect_available_watchlist_providers
11-
from .syncAPI import _load_state
12+
from .syncAPI import _load_state, _peek_state_key
13+
14+
15+
_WALL_CACHE_LOCK = threading.Lock()
16+
_WALL_CACHE: dict[str, Any] = {"key": None, "data": None}
17+
18+
19+
def _path_key(path: Any) -> tuple[str, int, int]:
20+
try:
21+
p = path if hasattr(path, "stat") else config_path()
22+
st = p.stat()
23+
mt = int(getattr(st, "st_mtime_ns", int(st.st_mtime * 1e9)))
24+
return (str(p), mt, int(st.st_size))
25+
except Exception:
26+
return (str(path or ""), 0, 0)
27+
28+
29+
def _cache_key(*, both_only: bool, active_only: bool, limit: int) -> tuple[Any, ...]:
30+
return (
31+
_peek_state_key(),
32+
_path_key(config_path()),
33+
bool(both_only),
34+
bool(active_only),
35+
int(limit or 0),
36+
)
1237

1338

1439
def _tmdb_api_key(cfg: dict[str, Any]) -> str:
@@ -70,6 +95,11 @@ def api_state_wall(
7095
active_only: bool = Query(False, description="Keep only items from configured providers"),
7196
limit: int = Query(0, ge=0, le=100, description="Optional item limit"),
7297
) -> dict[str, Any]:
98+
key = _cache_key(both_only=both_only, active_only=active_only, limit=limit)
99+
with _WALL_CACHE_LOCK:
100+
if _WALL_CACHE.get("key") == key and isinstance(_WALL_CACHE.get("data"), dict):
101+
return dict(_WALL_CACHE["data"])
102+
73103
cfg = load_config() or {}
74104
st = _load_state() or {}
75105
api_key = _tmdb_api_key(cfg)
@@ -90,9 +120,13 @@ def keep(it: dict[str, Any]) -> bool:
90120
if limit:
91121
items = items[:limit]
92122

93-
return {
123+
data = {
94124
"ok": True,
95125
"items": items,
96126
"missing_tmdb_key": not bool(api_key),
97127
"last_sync_epoch": st.get("last_sync_epoch") if isinstance(st, dict) else None,
98128
}
129+
with _WALL_CACHE_LOCK:
130+
_WALL_CACHE["key"] = key
131+
_WALL_CACHE["data"] = data
132+
return data

0 commit comments

Comments
 (0)