From 03392ca6355c4bddac39ce8f1da7e66cc2615086 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 17 Sep 2023 23:20:06 -0700 Subject: [PATCH] New: Optional 'downloadClientId' for pushed releases (cherry picked from commit fa5bfc3742c24c5730b77bf8178a423d98fdf50e) Closes #2934 --- .../Download/ProcessDownloadDecisions.cs | 122 ++++++++++++++---- .../Download/ProcessedDecisionResult.cs | 11 ++ .../Indexers/ReleasePushController.cs | 17 +-- 3 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 src/NzbDrone.Core/Download/ProcessedDecisionResult.cs diff --git a/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs b/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs index 41f8797bf..83010cad7 100644 --- a/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs +++ b/src/NzbDrone.Core/Download/ProcessDownloadDecisions.cs @@ -14,6 +14,7 @@ namespace NzbDrone.Core.Download public interface IProcessDownloadDecisions { Task ProcessDecisions(List decisions); + Task ProcessDecision(DownloadDecision decision, int? downloadClientId); } public class ProcessDownloadDecisions : IProcessDownloadDecisions @@ -40,8 +41,6 @@ namespace NzbDrone.Core.Download var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(qualifiedReports); var grabbed = new List(); var pending = new List(); - - //var failed = new List(); var rejected = decisions.Where(d => d.Rejected).ToList(); var pendingAddQueue = new List>(); @@ -51,7 +50,6 @@ namespace NzbDrone.Core.Download foreach (var report in prioritizedDecisions) { - var remoteBook = report.RemoteBook; var downloadProtocol = report.RemoteBook.Release.DownloadProtocol; //Skip if already grabbed @@ -73,37 +71,48 @@ namespace NzbDrone.Core.Download continue; } - try - { - _logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteBook.Release.Indexer, remoteBook.Release.IndexerPriority); - await _downloadService.DownloadReport(remoteBook, null); - grabbed.Add(report); - } - catch (ReleaseUnavailableException) - { - _logger.Warn("Failed to download release from indexer, no longer available. " + remoteBook); - rejected.Add(report); - } - catch (Exception ex) + var result = await ProcessDecisionInternal(report); + + switch (result) { - if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException) - { - _logger.Debug(ex, "Failed to send release to download client, storing until later. " + remoteBook); - PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable); + case ProcessedDecisionResult.Grabbed: + { + grabbed.Add(report); + break; + } + + case ProcessedDecisionResult.Pending: + { + PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.Delay); + break; + } - if (downloadProtocol == DownloadProtocol.Usenet) + case ProcessedDecisionResult.Rejected: { - usenetFailed = true; + rejected.Add(report); + break; } - else if (downloadProtocol == DownloadProtocol.Torrent) + + case ProcessedDecisionResult.Failed: { - torrentFailed = true; + PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable); + + if (downloadProtocol == DownloadProtocol.Usenet) + { + usenetFailed = true; + } + else if (downloadProtocol == DownloadProtocol.Torrent) + { + torrentFailed = true; + } + + break; + } + + case ProcessedDecisionResult.Skipped: + { + break; } - } - else - { - _logger.Warn(ex, "Couldn't add report to download queue. " + remoteBook); - } } } @@ -115,6 +124,30 @@ namespace NzbDrone.Core.Download return new ProcessedDecisions(grabbed, pending, rejected); } + public async Task ProcessDecision(DownloadDecision decision, int? downloadClientId) + { + if (decision == null) + { + return ProcessedDecisionResult.Skipped; + } + + if (decision.TemporarilyRejected) + { + _pendingReleaseService.Add(decision, PendingReleaseReason.Delay); + + return ProcessedDecisionResult.Pending; + } + + var result = await ProcessDecisionInternal(decision, downloadClientId); + + if (result == ProcessedDecisionResult.Failed) + { + _pendingReleaseService.Add(decision, PendingReleaseReason.DownloadClientUnavailable); + } + + return result; + } + internal List GetQualifiedReports(IEnumerable decisions) { //Process both approved and temporarily rejected @@ -148,5 +181,38 @@ namespace NzbDrone.Core.Download queue.Add(Tuple.Create(report, reason)); pending.Add(report); } + + private async Task ProcessDecisionInternal(DownloadDecision decision, int? downloadClientId = null) + { + var remoteBook = decision.RemoteBook; + + try + { + _logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteBook.Release.Indexer, remoteBook.Release.IndexerPriority); + await _downloadService.DownloadReport(remoteBook, downloadClientId); + + return ProcessedDecisionResult.Grabbed; + } + catch (ReleaseUnavailableException) + { + _logger.Warn("Failed to download release from indexer, no longer available. " + remoteBook); + return ProcessedDecisionResult.Rejected; + } + catch (Exception ex) + { + if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException) + { + _logger.Debug(ex, + "Failed to send release to download client, storing until later. " + remoteBook); + + return ProcessedDecisionResult.Failed; + } + else + { + _logger.Warn(ex, "Couldn't add report to download queue. " + remoteBook); + return ProcessedDecisionResult.Skipped; + } + } + } } } diff --git a/src/NzbDrone.Core/Download/ProcessedDecisionResult.cs b/src/NzbDrone.Core/Download/ProcessedDecisionResult.cs new file mode 100644 index 000000000..d1f27ed49 --- /dev/null +++ b/src/NzbDrone.Core/Download/ProcessedDecisionResult.cs @@ -0,0 +1,11 @@ +namespace NzbDrone.Core.Download +{ + public enum ProcessedDecisionResult + { + Grabbed, + Pending, + Rejected, + Failed, + Skipped + } +} diff --git a/src/Readarr.Api.V1/Indexers/ReleasePushController.cs b/src/Readarr.Api.V1/Indexers/ReleasePushController.cs index f2ee964ae..0c3cf66f2 100644 --- a/src/Readarr.Api.V1/Indexers/ReleasePushController.cs +++ b/src/Readarr.Api.V1/Indexers/ReleasePushController.cs @@ -53,22 +53,23 @@ namespace Readarr.Api.V1.Indexers ResolveIndexer(info); - List decisions; + DownloadDecision decision; lock (PushLock) { - decisions = _downloadDecisionMaker.GetRssDecision(new List { info }, true); - _downloadDecisionProcessor.ProcessDecisions(decisions).GetAwaiter().GetResult(); - } + var decisions = _downloadDecisionMaker.GetRssDecision(new List { info }, true); + + decision = decisions.FirstOrDefault(); - var firstDecision = decisions.FirstOrDefault(); + _downloadDecisionProcessor.ProcessDecision(decision, release.DownloadClientId).GetAwaiter().GetResult(); + } - if (firstDecision?.RemoteBook.ParsedBookInfo == null) + if (decision?.RemoteBook.ParsedBookInfo == null) { - throw new ValidationException(new List { new ValidationFailure("Title", "Unable to parse", release.Title) }); + throw new ValidationException(new List { new ("Title", "Unable to parse", release.Title) }); } - return MapDecisions(new[] { firstDecision }).First(); + return MapDecisions(new[] { decision }).First(); } private void ResolveIndexer(ReleaseInfo release)