Nothing files a virtual item, so every missing-episode setting and route is unreachable #196
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The read side of virtual items is finished and nothing ever writes one, so the
whole feature is unreachable.
What is already there:
crates/ephyra-db/src/query/filters.rs:390—Virtual::ExcludedandVirtual::OnlyspellIsVirtualItem = 0and= 1.crates/ephyra-http/src/routes/library/tv_shows.rs:424— a request namingIsMissingdecides for itself, and without one the account'sDisplayMissingEpisodesdecides.crates/ephyra-db/src/items/writes.rs:331—BaseItemscarries the column.What is not there: any writer. The scan files a row per file on disk, so
IsVirtualItemis0on every row this server has ever written.DisplayMissingEpisodescan therefore never change what a season lists, and/Shows/Upcoming— which is served,tv_shows.rs:32— can only answer out ofrows that have a file.
The task that would file them is permanently absent, and the reason is recorded
in the code:
What upstream does
A virtual episode is written by the TMDb provider rather than by the scan: the
series' episode list comes back from the database, the episodes with no file
are filed as rows with
IsVirtualItem = 1, andDisplayMissingEpisodes/DisplayUnairedEpisodesdecide per account whether a listing keeps them. Thescheduled task re-runs it for series whose next episode is near.
Where it would go here
crates/ephyra-app/src/metadata/tmdb/tv.rsalready fetches a season(
season, line 91) and an episode (episode, line 120) by number, so theepisode list a season answers with is most of the input. The writing end is
crates/ephyra-app/src/scan/ingest.rs, and the task would join the declaredset in
crates/ephyra-app/src/admin/tasks.rs— removing itsALWAYS_ABSENTentry is part of the change, and
absent()'s test asserts the list.Open
rows upstream users routinely turn off. The cheap half is honest: without it,
two account settings and one route are dead weight.
turned into a row, so it is D27's rule — the requests go in the cassette
(
crates/ephyra-app/corpus/fetched.json) and the rows upstream wrote go inthe answer key (
enriched.json), both regenerated together withcargo xtask reference gen-enriched-corpus. The enriched set is films; aseries with a gap in it would have to join it.
Done in
9576c87f…d984b844, and the scope question the issue asked has ananswer: build it, because the expensive half was already paid.
reference/scripts/make-sample-media.shalready lays down Firefly with 2 ofseason 1's 11 episodes and Twin Peaks with 1 of season 1's 8 — so growing the
image's library, the part that redraws every snapshot cut against it, was
already done. Only the provider had to be turned on. What it cost was 58 rows
and about 15 MB of answer key.
Against that:
Virtual::Excluded/Only,DisplayMissingEpisodes,DisplayUnairedEpisodesand/Shows/Upcomingwere all unreachable — twoaccount settings and a route that report a choice being honoured and could
not be.
What it is
crates/ephyra-app/src/scan/run/announced.rsis upstream'sTmdbMissingEpisodeProvider: the season numbers and the episode list a passalready asks for, the episodes with no file behind them filed through
Write::without_a_file(), andIsVirtualItembound in the scan's row.TmdbRefreshUpcomingEpisodesleaves the absent list and joins the declaredtasks where a library asked for them.
One thing the mutations found
Gating the grace period on
known.contains(id)was wrong and could neverfire: the reader is
WHERE Path IS NOT NULL, so a placeholder is never readback. The id is named unconditionally now — a pass removes what it did not
name, so naming one that is not there removes nothing.
The cassette could not be extended
--extendfailed with nothing offered for 8 of the pictures is the fileupstream kept: the committed key was cut on the 27th of August, the local
snapshot on the 1st of September, and the database had moved between them. Both
halves were re-cut from one moment instead, which is what D28 prescribes.
Two committed tests had to follow the re-cut, and one of them was a real
finding rather than drift: a film's blob expected
"DefaultVideoStreamIndex": null, and upstream's serializer omits a null member. The fixture settles it —a physical episode carries
0and a virtual one omits it — so the port omitsit too.
Divergences, all recorded in D44
The day is an input rather than the clock, so two runs of a scan cannot
disagree; season zero is not asked for unless specials are wanted; the
per-library opt-in is a library setting rather than a plugin's list; the
refresh interval is a task trigger rather than a second place to store the
same number; pruning is the sweep a pass already does; and the task runs a
pass over the libraries that asked rather than refreshing series one at a
time.
For whoever regenerates next
reference/snapshots/enrichedis re-cut and now matches the committed corpus.The stale one it replaced was eleven days older than the key — a regeneration
against it would have produced a wrong answer key without saying so.