video enrichment: stop OMDb traceback spam from the detail/drawer path too

the earlier latch only covered _backfill_ratings. _fill_tmdb_ratings (hit by
tmdb_full_detail → detail pages, the download drawer's meta endpoint, the airing
automation's status lookups) still re-hit OMDb once per title and dumped a traceback
each time once over quota. now it shares the same _omdb_blocked latch: checks it before
calling, sets it + logs ONE quiet warning on OMDbAuthError. (the bulk OMDb worker already
cools down + auto-resumes, so it was never the spammer.) tested.
This commit is contained in:
BoulderBadgeDad 2026-06-26 16:28:37 -07:00
parent 75f23641b3
commit 11c0c62a7e
2 changed files with 32 additions and 1 deletions

View file

@ -567,13 +567,19 @@ class VideoEnrichmentEngine:
def _fill_tmdb_ratings(self, d) -> None:
imdb_id = d.get("imdb_id")
ow = self.workers.get("omdb")
if not imdb_id or not ow or not getattr(ow.client, "enabled", False):
# share the same daily-limit latch as _backfill_ratings — once OMDb is over quota,
# every detail fetch would otherwise re-hit it and dump a traceback per title.
if (not imdb_id or not ow or not getattr(ow.client, "enabled", False)
or getattr(self, "_omdb_blocked", False)):
return
try:
r = ow.client.ratings(imdb_id) or {}
for k in ("imdb_rating", "rt_rating", "metacritic"):
if r.get(k) is not None:
d[k] = r[k]
except OMDbAuthError as e:
self._omdb_blocked = True
logger.warning("OMDb ratings paused for this run: %s", e)
except Exception:
logger.exception("tmdb_detail ratings failed for %s", imdb_id)

View file

@ -151,6 +151,31 @@ def test_omdb_limit_latches_off_and_stops_hammering():
assert rc.n == 1 # only the first attempt ever reached OMDb
def test_tmdb_detail_ratings_share_the_same_latch():
# the detail/drawer path (_fill_tmdb_ratings) must honour + set the SAME latch — it was
# the source of the per-title traceback spam on the download drawer / detail pages.
from core.video.enrichment.engine import VideoEnrichmentEngine
from core.video.enrichment.clients import OMDbAuthError
class _RC:
enabled = True
def __init__(self):
self.n = 0
def ratings(self, imdb):
self.n += 1
raise OMDbAuthError("Request limit reached!")
eng = VideoEnrichmentEngine.__new__(VideoEnrichmentEngine)
rc = _RC()
eng.workers = {"omdb": type("W", (), {"client": rc})()}
eng._fill_tmdb_ratings({"imdb_id": "tt1"}) # hits the limit → latches (no raise out)
assert getattr(eng, "_omdb_blocked", False) is True
eng._fill_tmdb_ratings({"imdb_id": "tt2"}) # short-circuits before calling OMDb
assert rc.n == 1
# ── wiring contract ───────────────────────────────────────────────────────────
def test_seeded_before_the_airing_automation():
import core.automation_engine as ae