aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-26 14:28:13 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-26 14:28:13 +0200
commiteccd465f8954bfd49c3f7d8f02446bc2aa5c4338 (patch)
tree0033f9232c56ca79c4838795c1cf5bdab13bc55f /packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py
parentfc761e7df40eac828d4e9858fab56958078c928b (diff)
downloadmeshbay-main.tar.gz
fix(node,client): query TMDB only once a language is chosen, in that languageHEADmain
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 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py')
-rw-r--r--packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py80
1 files changed, 80 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py b/packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py
new file mode 100644
index 0000000..cf1ecdc
--- /dev/null
+++ b/packages/meshbay-node/tests/test_tmdb_language_change_clears_cache.py
@@ -0,0 +1,80 @@
+"""
+Changing the node's TMDB language wipes the cached fiches (`ops.set_tmdb_config`).
+
+The cache is keyed by TMDB id alone and records no language, so a fiche fetched
+under the old language would be served for its whole 30-day TTL. An operator who
+sets the language *after* browsing the library once — the ordinary order, since
+browsing is what triggers the lazy fetch — would keep seeing the old language
+otherwise (found live: a whole library indexed in English before "Français" was
+chosen, 2026-09-26). Only the language change clears; a no-op re-set or a
+token-only change must leave the cache alone, or every unrelated settings save
+would throw the library's metadata away.
+"""
+
+import pytest
+from meshbay_node import ops
+from meshbay_node.media_cache import MediaCache
+from meshbay_node.roster import Roster
+
+pytestmark = pytest.mark.asyncio
+
+
+async def _state(tmp_path):
+ roster = Roster(db_path=tmp_path / "roster.db")
+ await roster.open()
+ cache = MediaCache(db_path=tmp_path / "media_cache.db")
+ await cache.open()
+ state = {"roster": roster, "media_cache": cache, "node_user_id": "operator"}
+ return state, roster, cache
+
+
+async def _seed(cache):
+ await cache.set_tmdb_meta("1668", "tv", {"name": "Friends"})
+ await cache.set_season_meta("1668", 1, {"overview": "Season one"})
+
+
+async def test_changing_language_clears_the_metadata_cache(tmp_path):
+ state, roster, cache = await _state(tmp_path)
+ try:
+ await ops.set_tmdb_config(state, language="") # start at default/English
+ await _seed(cache)
+
+ await ops.set_tmdb_config(state, language="fr-FR")
+
+ assert await cache.get_tmdb_meta("1668", "tv") is None
+ assert await cache.get_season_meta("1668", 1) is None
+ finally:
+ await roster.close()
+ await cache.close()
+
+
+async def test_re_setting_the_same_language_keeps_the_cache(tmp_path):
+ state, roster, cache = await _state(tmp_path)
+ try:
+ await ops.set_tmdb_config(state, language="fr-FR")
+ await _seed(cache)
+
+ await ops.set_tmdb_config(state, language="fr-FR")
+
+ assert await cache.get_tmdb_meta("1668", "tv") == {"name": "Friends"}
+ assert await cache.get_season_meta("1668", 1) == {"overview": "Season one"}
+ finally:
+ await roster.close()
+ await cache.close()
+
+
+async def test_token_only_change_keeps_the_cache(tmp_path):
+ state, roster, cache = await _state(tmp_path)
+ try:
+ await ops.set_tmdb_config(state, language="fr-FR")
+ await _seed(cache)
+
+ # language=None means "leave the language" — not a language change,
+ # so the fiches stay.
+ await ops.set_tmdb_config(state, token="a-custom-token")
+
+ assert await cache.get_tmdb_meta("1668", "tv") == {"name": "Friends"}
+ assert await cache.get_season_meta("1668", 1) == {"overview": "Season one"}
+ finally:
+ await roster.close()
+ await cache.close()