Add premiumize cache availability + opt-in OnlyDownloadCached gate - #1036
Open
dabonzo wants to merge 4 commits into
Open
Add premiumize cache availability + opt-in OnlyDownloadCached gate#1036dabonzo wants to merge 4 commits into
dabonzo wants to merge 4 commits into
Conversation
…nabled An uncached torrent is marked completed-with-error before any transfer is created, which the qBittorrent-emulation add endpoint reports as the synchronous "Fails." response - download managers like Sonarr and Radarr treat that as a rejected release and fall through to the next candidate in the same search pass. Rejected hashes are remembered for 30 minutes and answered from memory (with a times-seen counter in the log), since download managers re-offer the same release on every RSS/search pass. Cache-check errors fail open; rate limits pause the dequeue as before. NZBs bypass the gate (no torrent-cache concept).
Two independent adversarial review passes over the branch converged on the same defects; all confirmed findings fixed: - OnlyDownloadCached moves from the shared DbSettingsDefaults (where it rendered as four checkboxes, three of them dead) to DbSettingsProvider: one checkbox, one config key (Provider:OnlyDownloadCached), read where the gate actually runs. Provider-level policy, not a per-torrent default. - The gate only runs when the provider actually implements an availability check (new IDebridClient.SupportsAvailabilityCheck, default false; Premiumize and TorBox true). Enabling the setting on RealDebrid/ AllDebrid/DebridLink previously rejected 100% of torrents forever, since their GetAvailableFiles are stubs returning empty. Now it logs a clear warning and stays inactive. - The gate runs BEFORE the provider lock (read-only probe; must not extend the lock hold for every queued torrent). - GetAvailableFiles switches from the Premiumize.NET library to raw HTTP: the library never inspects HTTP status codes, so a 429 with an unrecognized body escaped rate-limit classification. Error answers now THROW (gate fails open) instead of reading as "not cached"; only a well-formed success may reject. - AddQueued replaces a dead pre-provider row (completed-with-error, never added) instead of returning it - a re-offered release now gets a real re-check instead of answering "Fails." from the stale row forever. - Error-cleanup only deletes local files for torrents that reached the provider (a rejected torrent never downloaded anything; a recursive name-match delete could hit unrelated content). - A human Retry forgets the hash from the uncached-memory so the re-add reaches the provider. - Uncached-memory entries are provider-scoped and pruned opportunistically above a size threshold; entry is a readonly record struct per house pattern. Warning logged when rejecting with DeleteOnError=0. - New composed gate test: real Torrents + real PremiumizeDebridClient over scripted HTTP - rejected-without-transfer, added-when-cached, and answered-from-memory paths. 279 tests green (was 261 at branch point).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
Two related changes for debrid providers, both scoped to torrents.
1. A real
GetAvailableFilesfor premiumize. Today the premiumize implementation is a stub:so premiumize always reports nothing as cached. This implements it against premiumize's
/cache/check, giving it the same meaningful availability answer TorBox already provides.2. An opt-in
OnlyDownloadCachedprovider setting (defaultfalse). When enabled, adding atorrent whose hash is not cached at the provider is rejected at add time instead of being queued.
For Sonarr/Radarr users that rejection is the point: it lets the *arr fall through to the next
release rather than sitting on a torrent the provider will try to leech from peers.
Why
On premiumize a cached torrent completes instantly and costs a fraction of the fair-use budget, while
an uncached one can stall at 0 B/s from 0 peers indefinitely. Without a working cache check there is
no way to tell those apart before committing to the download.
Design notes
settings.Current.Provider.OnlyDownloadCachedand asks whichever client is configured. On aprovider with no availability check it logs a warning and stays inactive rather than rejecting
everything.
down the download fails on its own. Failing closed would silently reject a whole library.
torrent.Type != DownloadType.Nzb) — cache checking has no meaning there.same release each RSS pass doesn't re-query, and an "uncached" verdict can't carry across a
provider switch.
never inspects HTTP status codes, so a 429 whose body matches no documented phrase would be
misread as "not cached". Only a well-formed success answer is allowed to say that.
One caveat worth knowing
Rejected torrents are marked errored, so they are only cleaned up when Delete download when in
error is above 0. The gate logs a warning when that setting is 0, since rejected entries would
otherwise accumulate.
Tests
Adds 18 test methods across three files (
PremiumizeDebridClientTest,TorrentsCacheGateTest,UncachedHashMemoryTest): cache-check parsing, cached/uncached/rate-limited/error responses, thegate's accept and reject paths with the setting on and off, and the expiry and provider-scoping of
the uncached-hash memory. Full suite green on this branch (243 Service + 37 Web).
Field use
I've been running this for the last 9 days on a Sonarr/Radarr + premiumize setup, as the sole
download client for both protocols. Happy to answer questions about how it behaves in practice.
Overlap with #1014
#1014 (open) touches
PremiumizeDebridClient.cs,Torrents.csandPremiumizeDebridClientTest.cs—the three files this PR changes most. This branch is rebased on current
main(e479404) and appliescleanly there. If you'd rather merge #1014 first, say so and I'll rebase and resolve.