From eccd465f8954bfd49c3f7d8f02446bc2aa5c4338 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 26 Sep 2026 14:28:13 +0200 Subject: fix(node,client): query TMDB only once a language is chosen, in that language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TMDB fiches are fetched lazily, on browse, and the fetch used to run whatever the moment it was first triggered — routinely before the operator had opened settings and picked a language, so it queried in TMDB's English default. Then the fiche was cached by tmdb_id alone, with no note of language and a 30-day TTL, so switching to the intended language afterwards changed nothing: the English fiche was served until it expired. The operator's only recourse was to find and wipe the cache by hand (found live 2026-09-26: a whole library indexed in English although "Français" had been chosen). Two rules now, both there to make the first fetch the right language rather than English-then-corrected, and to stop the doubled requests that eventually get a node rate-limited: - No language configured, no query. media_meta_req/season_meta_req answer confidence 0 and make no TMDB call while tmdb_language is unset; the fetch waits for the operator's choice, so the first (and only) query is in it. English is now a first-class choice (en-US), not the default of skipping the setting. - Changing the language wipes the metadata cache (ops.set_tmdb_config), so the new language takes effect on an already-browsed library. The file->tmdb matches are language-independent and kept. The client refetches on the tmdb_config_ack that carries the new language, so the grid updates without a page reload. docs/MESHBAY_DESIGN.md §9.7 states both rules; tests cover the gate and the cache wipe, and two existing handler harnesses now declare a language. Co-Authored-By: Claude Opus 4.8 --- .../meshbay-node/src/meshbay_node/media_cache.py | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'packages/meshbay-node/src/meshbay_node/media_cache.py') diff --git a/packages/meshbay-node/src/meshbay_node/media_cache.py b/packages/meshbay-node/src/meshbay_node/media_cache.py index 9c692ca..17262bc 100644 --- a/packages/meshbay-node/src/meshbay_node/media_cache.py +++ b/packages/meshbay-node/src/meshbay_node/media_cache.py @@ -290,6 +290,33 @@ class MediaCache: await self._db.commit() return cur.rowcount + async def clear_tmdb_metadata(self) -> int: + """ + Drop every cached TMDB fiche — show/movie details (`tmdb_meta`) and + per-season metadata (`season_meta`) — so the next `media_meta_req` + refetches each from TMDB. The file->tmdb *matches* (`file_tmdb`) are + language-independent and deliberately kept: the match is the same + title whatever language its blurb is in. + + Called when the node's TMDB *language* changes (`ops.set_tmdb_config`). + A fiche is cached under `tmdb_id` alone, on purpose — there is only + ever one node-wide language, so a per-language key would be dead + weight — which is exactly why the language it was fetched in is not + recorded, and a fiche cached under the old language would otherwise be + served unchanged for its whole 30-day TTL after the operator switched. + Wiping them on the switch is what makes the new language actually take + effect on a library that has already been browsed. Returns the number + of rows removed. + """ + if not self._db: + return 0 + cur = await self._db.execute("DELETE FROM tmdb_meta") + removed = cur.rowcount + cur = await self._db.execute("DELETE FROM season_meta") + removed += cur.rowcount + await self._db.commit() + return removed + # ── tmdb id -> metadata json ───────────────────────────────────────────── async def get_tmdb_meta(self, tmdb_id: str, media_type: str) -> dict | None: -- cgit v1.2.3