fix(plex,audit): E30 review round 1 — the people job keeps going, HU genres everywhere, results as data
- people_enrich: a failed TMDB lookup or a dead headshot is skipped, not the end of the run (a dead file is marked and left for a week; three failures in a row end it); portraits wait for the Plex module switch; a no-Plex original keeps its own cache key, so the resize still replaces it; the job entry lives in the plex domain (run_people_enrich) - person-image takes only a headshot-shaped CDN url (no query variants of one file) - every synced row gets Hungarian genres, and a HU genre filter matches the word as picked too; migration 0094 fills the rows no overlay reached - a job run's audit row carries its result as data; audit_clear / demo_reset store their counts - one credit-column list for the prune and the enrichment order; _overlay_pass typed - tests: batch skip + stop, HU bio stored, dead headshots, module switch, the person-image route, the job body, genre filter + facet write + twin fallback, tagline/summary fallbacks, audit data, the reader's alphabet at every remaining collated() call site
This commit is contained in:
@@ -8,6 +8,9 @@ few hundred MB at most for a big library — acceptable, matching the download d
|
||||
The cache directory (``cache.CACHE_DIR``) is shared with the subtitle cache (see ``subtitles.py``).
|
||||
"""
|
||||
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
from fastapi import Response
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -78,6 +81,27 @@ def drop(key: str) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def mark_miss(key: str) -> None:
|
||||
"""Remember that `key`'s source could not be fetched (an empty `.miss` file; its mtime is when), so
|
||||
a prefetch can leave a dead source alone for a while. Best-effort."""
|
||||
try:
|
||||
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
(CACHE_DIR / f"{key}.miss").touch()
|
||||
# silent-ok: without the mark the dead source is only asked for again on the next run.
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def missed_within(key: str, age: timedelta) -> bool:
|
||||
"""`key` was marked as a miss less than `age` ago."""
|
||||
try:
|
||||
mtime = (CACHE_DIR / f"{key}.miss").stat().st_mtime
|
||||
# silent-ok: no mark (the usual case).
|
||||
except OSError:
|
||||
return False
|
||||
return time.time() - mtime < age.total_seconds()
|
||||
|
||||
|
||||
def write(key: str, data: bytes, ct: str) -> None:
|
||||
ext = _CT_EXT.get((ct or "").split(";")[0].strip(), "jpg")
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user