fix(plex): make the cast gate self-correcting as well as non-shrinking (B-sub-2 review)

The union form fixed the downgrade but removed the per-sync self-healing: a name
Plex removed from an unenriched title lingered in cast_names/people_text until
enrichment. Replace the union with a length guard — take the fresh listing
unless it is shorter than what is stored. A stored cast longer than the ~20-cap
listing can only be an enriched fuller list (kept, so a watermark reset never
downgrades it); at or below the cap the stored value is itself listing-sourced,
so replacing it with the current listing stays self-correcting.
This commit is contained in:
2026-08-18 00:58:13 +02:00
parent 4ce0a702f4
commit 0653203d81
+8 -6
View File
@@ -309,13 +309,15 @@ def _apply_facet_fields(row, meta: dict) -> None:
# person-page cast filter for names past the top ~20. The watermark gate below (`people_enriched_at
# is None`) normally protects this, but it is NOT enough on its own: a migration that resets the
# watermark re-opens the regression (0065 nulled it, which is exactly how the S5b fix got undone in
# prod). So guard STRUCTURALLY too — union the listing cast onto whatever is stored, never dropping a
# name we already have. On a fresh row (empty `cast_names`) this seeds the top ~20; on a row whose
# watermark was reset but whose fuller cast survives, it keeps the fuller cast. Robust to any future
# watermark reset, not just this one.
# prod). So guard STRUCTURALLY too, by LENGTH: take the fresh listing UNLESS it is shorter than what
# is stored. A stored cast longer than the ~20-cap listing can only be an enriched fuller list, so
# keep it (robust to any watermark reset); at or below the cap the stored value is itself
# listing-sourced, so replacing it with the current listing stays self-correcting when Plex edits
# the cast (a pure union never would).
if row.people_enriched_at is None:
merged = list(dict.fromkeys((row.cast_names or []) + (_tags(meta, "Role", limit=20) or [])))
row.cast_names = merged or None
listing_cast = _tags(meta, "Role", limit=20)
if len(row.cast_names or []) <= len(listing_cast or []):
row.cast_names = listing_cast
people = list(dict.fromkeys((row.directors or []) + (row.cast_names or [])))
row.people_text = " ".join(people) or None