feat(daemon): grab pipeline for wanted movies #77
Reference in New Issue
Block a user
Delete Branch "issue/22-grab-pipeline"
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?
Closes #22.
A wanted movie with no file is now searched, scored and sent to Transmission,
and the
Grabis recorded. There is no grab delay (§5.4), and the label plusboth seeding limits are set at add time (§7.1, §7.3).
Restarting mid-flight does not grab twice: a title with a live grab is not a
gap, selection is a total order over the candidate set, and
torrent-addiskeyed on the infohash — so a crash between the add and the insert heals on the
next tick rather than leaving a second torrent. There is a test for exactly
that.
The policy-row-to-
arr-coremapping moved intoarr-db, where both themanual-search API and the daemon read it, replacing the copy in
arr-api.Out of scope, each with its own issue: search backoff and release-date gating
(#26), RSS matching (#27), import (#23), blacklist and hard/soft fail (#24),
per-tracker seeding rules and the reaper (#25). Seeding limits come from
config defaults until #25 gives them a home, and the daemon scores with
arr-corewhilearr-apistill uses its placeholder (#68).Verification
just cilocally: fmt, clippy-D warnings,cargo machete, 175 testspassing,
biome ciandtsc.New tests in
crates/arr-daemon/src/grab.rsrun the action against a wiremockProwlarr and a Transmission fake that dedupes on the infohash like the real
one:
WEB-DL beats the 60 GB remux while the CAM is filtered out
one torrent and one grab
seedRatioLimit,seedIdleLimitand download dir are on the adddownloaded@@ -0,0 +91,4 @@return Ok(outcomes);}let indexers = self.prowlarr.indexers().await?;The reconcile lane has a 25 s timeout, but
indexers()probes capabilities sequentially with a 30 s HTTP timeout. One slow tracker cancels the whole action before any targeted search starts. Bound or parallelize discovery, or cache it outside this tick.Fixed in
4502abb. Discovery is now bounded and cached:searchable_indexers()wrapsindexers()in an 8 s timeout and reuses the result for 15 minutes, so a slow tracker costs at most 8 s of the 25 s budget and only on a cache refresh. A refresh that times out or fails keeps the previous list and logs, instead of failing the tick; only an empty cache turns it into an error.Two tests cover it:
indexer_discovery_is_cached_across_ticksasserts one enumeration across two ticks, anda_stalled_discovery_gives_up_instead_of_hangingasserts the timeout wins against a stalled Prowlarr.Parallelising the caps probes inside
arr-indexerwould help too, but that belongs to that crate rather than this issue.Merged
origin/main(#71, #74, #75) rather than rebasing.crates/arr-api/src/search.rsconflicted with #74; resolved onto main's version, then re-applied the move of the policy-row mapping intoarr-db. #74'spolicy_row_uses_persisted_score_weightsmoved with it ascolumns_map_without_a_row.Two failures came in from main and are fixed here, unrelated to this issue:
search.rsusedMovieOverrides::default()in a test after #71 renamed the type toTitleOverrides— main does not compile--all-targets.roots_carry_their_policy_namestill expected 2 roots after #71 seeded the two TV roots.Reviewed
4502abbb04edcc3db8bf77b1fb00ccae13e9d5a0. No findings.Reviewed
acda6c5d5e82dbf29b64d5c7ded9c1ca34ca6843. No findings.