fix(e5): address code-review findings (TMDB guid media_type, search ingest guard, discover keying)
Follow-ups from the epic-end /code-review of the E5 branch: - tmdb.resolve_recs + people._resolve_known_for: match recommendations/ credits to the library bucketed by media_type. TMDB movie ids and tv ids are independent sequences, so a bare `tmdb:<id>` match could deep-link a movie rec to an unrelated show (or vice-versa) on a numeric collision. Regression test added (test_resolve_recs_matches_by_media_type_not_bare_id). - routes/search: wrap the _ingest_candidates call so a DB/enrich failure degrades to a 422 with a message instead of a bare 500 hidden behind the FE's generic "search failed" (extends the B-core-1 rationale); rollback on failure. Stamp enriched_at with its own timestamp taken after the enrich, not the stub-insert placeholder. - routes/plex/discover: key serialized cards back by rating_key (globally unique in Plex) instead of id(obj); fix the stale rows 3-tuple annotation.
This commit is contained in:
@@ -36,24 +36,32 @@ def _resolve_known_for(
|
||||
popularity order. Matched by the canonical guid `tmdb:<id>`; out-of-library credits are dropped."""
|
||||
if not known_for:
|
||||
return []
|
||||
guids = [f"tmdb:{k['tmdb_id']}" for k in known_for if k.get("tmdb_id")]
|
||||
if not guids:
|
||||
# Bucket by media_type: TMDB movie ids and tv ids collide numerically, so a movie credit must only
|
||||
# match a library movie and a tv credit only a library show (mirrors tmdb.resolve_recs). Matching
|
||||
# blind to media_type would render a tv credit as an unrelated movie whose tmdb id happens to match.
|
||||
movie_guids = [
|
||||
f"tmdb:{k['tmdb_id']}" for k in known_for if k.get("tmdb_id") and k.get("media_type") != "tv"
|
||||
]
|
||||
tv_guids = [
|
||||
f"tmdb:{k['tmdb_id']}" for k in known_for if k.get("tmdb_id") and k.get("media_type") == "tv"
|
||||
]
|
||||
if not movie_guids and not tv_guids:
|
||||
return []
|
||||
movies: dict[str, PlexItem] = {}
|
||||
if movie_lib_ids:
|
||||
if movie_lib_ids and movie_guids:
|
||||
for m in db.execute(
|
||||
select(PlexItem).where(
|
||||
PlexItem.kind == "movie",
|
||||
PlexItem.library_id.in_(movie_lib_ids),
|
||||
PlexItem.guid.in_(guids),
|
||||
PlexItem.guid.in_(movie_guids),
|
||||
)
|
||||
).scalars():
|
||||
movies.setdefault(m.guid, m)
|
||||
shows: dict[str, PlexShow] = {}
|
||||
if show_lib_ids:
|
||||
if show_lib_ids and tv_guids:
|
||||
for s in db.execute(
|
||||
select(PlexShow).where(
|
||||
PlexShow.library_id.in_(show_lib_ids), PlexShow.guid.in_(guids)
|
||||
PlexShow.library_id.in_(show_lib_ids), PlexShow.guid.in_(tv_guids)
|
||||
)
|
||||
).scalars():
|
||||
shows.setdefault(s.guid, s)
|
||||
@@ -70,10 +78,12 @@ def _resolve_known_for(
|
||||
out: list[dict] = []
|
||||
for k in known_for:
|
||||
g = f"tmdb:{k.get('tmdb_id')}"
|
||||
if g in movies:
|
||||
# A credit resolves against its OWN media_type's bucket only.
|
||||
if k.get("media_type") == "tv":
|
||||
if g in shows:
|
||||
out.append(show_card(shows[g], show_statuses.get(shows[g].id, "new")))
|
||||
elif g in movies:
|
||||
out.append(movie_card(movies[g], m_states.get(movies[g].id)))
|
||||
elif g in shows:
|
||||
out.append(show_card(shows[g], show_statuses.get(shows[g].id, "new")))
|
||||
return out
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user