Hard/soft fail handling and release blacklist #87
Reference in New Issue
Block a user
Delete Branch "issue/24-fail-handling"
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 #24. DESIGN.md §5.7, §6.3.
The blacklist moves out of the grab loop into
arr-db::blacklist, and is applied where a release is classified rather than where one is picked. That gets §6.3's "including by RSS" for free — RSS sync will call the samestore_release— and it makes the stored row say why: a blacklisted release isrejectedunder the ruleblacklisted, so §9.3's manual view names it instead of offering it as a clean match.Both keys now do work. The normalised name catches a re-upload; the infohash catches the same torrent re-listed under a new name. A
.torrentlink hides its infohash until Transmission has fetched it, so that case is caught after the add: the name is blacklisted too, nograbsrow is written, and the torrent is removed only when this tick added it — a duplicate is left seeding (§7.3).Soft fails already stored a waiver.
GET /api/movies/{movie_id}/filesis what carries it out, as the relaxed rule's name, sharing its vocabulary withRelease::rejected_rule.A hard fail still blacklists, fails the grab and reopens the gap; the next candidate comes from the next tick's search. Neither failure mode touches the torrent.
Not in scope: a grab whose torrent has vanished from Transmission. Two comments deferred that to this issue, but a hand-removed torrent is neither a hard nor a soft fail — filed as #86 and the comments now point there.
Verification
just ci— 237 tests, all passing. New coverage:arr-db blacklist::tests— both keys recorded and matched, no duplicate rows per failure, magnet infohash blocks a renamed candidategrab::tests::a_blacklisted_release_is_cached_as_rejectedgrab::tests::a_blacklisted_infohash_never_becomes_a_grabimport::tests::an_english_only_kids_import_carries_a_waivermovies::tests::a_movie_file_carries_its_waiversearch::tests::manual_releases_are_classified_and_name_rejection_rulesextended with the blacklisted case🤖 Generated with Claude Code
The blacklist moves to arr-db so every trigger that classifies a release shares one check — targeted search today, RSS matching when it lands. Applying it during classification rather than at selection also makes the stored row say `blacklisted`, which is what keeps §9.3's manual view from offering a hard-failed release as a clean match. Both §6.3 keys now do work: the normalised name catches a re-upload, and the infohash catches the same torrent re-listed under a new name — the latter only after Transmission has fetched a `.torrent`, so that grab is undone rather than recorded. Soft-failed imports already stored a waiver; `GET /api/movies/{id}/files` is what carries it out. Closes #24 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>@@ -393,0 +421,4 @@release_name: &str,added: &arr_dl::AddedTorrent,) -> Result<(), GrabError> {blacklist::add(The post-add hash check blacklists the release name but leaves the
releasesrow written duringstore_releasemarked eligible. Until another search overwrites it,GET /api/movies/{id}/releasesoffers this known-blacklisted.torrentas eligible. Updatewinner.idto rejected withblacklistedhere.@@ -393,0 +421,4 @@winner: &Eligible,added: &arr_dl::AddedTorrent,) -> Result<(), GrabError> {let release_name = &winner.name;Fixed in
b224136.drop_blacklisted_torrentnow writes the row back asrejectedwith ruleblacklistedbefore it decides what to do with the torrent, so the cached row stops reading eligible in the same tick that refuses the release rather than waiting for the next search to overwrite it.a_blacklisted_infohash_never_becomes_a_grabasserts the verdict and the rule alongside the existing grab and torrent assertions.