Deep-review round 4, backend half. - The periodic HLS reaper (round 3) applied the "finished and unfetched for 30 s" rule that only a NEW session request may apply. A remux finishes long before the film, and a paused player with a full buffer fetches nothing, so a one-minute pause killed the session and playback died ~30 s after resuming. The periodic pass is `reap_abandoned` now (the long idle limit, finished or not). - A subtitle `publish` that could not keep its output (full / read-only cache volume) returned quietly, so every poll queued the window and the whole-container pass again. It reports failure and the pass is backed off like a failed read; a cached VTT that cannot be READ is answered `unavailable` (`cache_unreadable`) instead of scheduling reads that can never land. - The subtitle routes bound `rating_key` / `sub_ord` (they become a cache file name: a 250-digit one was ENAMETOOLONG, which pathlib's exists() re-raises -> a 500), and the cache helpers no longer throw on such a name. - One app-wide handler turns psycopg's "text fields cannot contain NUL" DataError into a 422: round 3 guarded only the by-rating_key lookup, and `contains=`, `contains_group=`, reorder/bulk key lists and the collection search still 500'd. - The hand-written `db.get(...) is None -> 404 "Unknown ..."` siblings use `get_or_404` with a `what` (channel / video / user), so the Hungarian UI no longer shows English for a gone row.
22 lines
981 B
Python
22 lines
981 B
Python
"""Small shared Plex row lookups, so the get-by-rating_key pattern lives in one place."""
|
|
|
|
from typing import TypeVar
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
_M = TypeVar("_M")
|
|
|
|
|
|
def by_rating_key(db: Session, model: type[_M], rating_key: str) -> _M | None:
|
|
"""The mirrored row for a Plex rating_key, or None. `model` is any of the rating_key-keyed Plex
|
|
tables (PlexItem / PlexShow / PlexSeason / PlexCollection); the return type is that model, so call
|
|
sites keep their `Model | None` static type.
|
|
|
|
A key with a NUL in it (`%00` in a path segment) names no row — a 404, like any unknown key.
|
|
Postgres refuses NUL in text, so asking would be a DataError; the app-wide handler turns the
|
|
places that DO ask (lists and filters compared to rating_key) into a 422 (see main.py)."""
|
|
if "\x00" in str(rating_key):
|
|
return None
|
|
return db.execute(select(model).where(model.rating_key == str(rating_key))).scalars().first()
|