1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-19 17:32:38 +01:00

New: Optional 'downloadClientId' for pushed releases

(cherry picked from commit fa5bfc3742c24c5730b77bf8178a423d98fdf50e)

Closes #9190
This commit is contained in:
Mark McDowall 2023-09-17 23:20:06 -07:00 committed by Bogdan
parent bbeb4d7b5f
commit 4e01fa57fd
3 changed files with 115 additions and 34 deletions

View File

@ -14,6 +14,7 @@ namespace NzbDrone.Core.Download
public interface IProcessDownloadDecisions public interface IProcessDownloadDecisions
{ {
Task<ProcessedDecisions> ProcessDecisions(List<DownloadDecision> decisions); Task<ProcessedDecisions> ProcessDecisions(List<DownloadDecision> decisions);
Task<ProcessedDecisionResult> ProcessDecision(DownloadDecision decision, int? downloadClientId);
} }
public class ProcessDownloadDecisions : IProcessDownloadDecisions public class ProcessDownloadDecisions : IProcessDownloadDecisions
@ -49,7 +50,6 @@ public async Task<ProcessedDecisions> ProcessDecisions(List<DownloadDecision> de
foreach (var report in prioritizedDecisions) foreach (var report in prioritizedDecisions)
{ {
var remoteMovie = report.RemoteMovie;
var downloadProtocol = report.RemoteMovie.Release.DownloadProtocol; var downloadProtocol = report.RemoteMovie.Release.DownloadProtocol;
// Skip if already grabbed // Skip if already grabbed
@ -71,22 +71,30 @@ public async Task<ProcessedDecisions> ProcessDecisions(List<DownloadDecision> de
continue; continue;
} }
try var result = await ProcessDecisionInternal(report);
switch (result)
{
case ProcessedDecisionResult.Grabbed:
{ {
_logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteMovie.Release.Indexer, remoteMovie.Release.IndexerPriority);
await _downloadService.DownloadReport(remoteMovie, null);
grabbed.Add(report); grabbed.Add(report);
break;
} }
catch (ReleaseUnavailableException)
case ProcessedDecisionResult.Pending:
{
PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.Delay);
break;
}
case ProcessedDecisionResult.Rejected:
{ {
_logger.Warn("Failed to download release from indexer, no longer available. " + remoteMovie);
rejected.Add(report); rejected.Add(report);
break;
} }
catch (Exception ex)
case ProcessedDecisionResult.Failed:
{ {
if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException)
{
_logger.Debug(ex, "Failed to send release to download client, storing until later. " + remoteMovie);
PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable); PreparePending(pendingAddQueue, grabbed, pending, report, PendingReleaseReason.DownloadClientUnavailable);
if (downloadProtocol == DownloadProtocol.Usenet) if (downloadProtocol == DownloadProtocol.Usenet)
@ -97,10 +105,13 @@ public async Task<ProcessedDecisions> ProcessDecisions(List<DownloadDecision> de
{ {
torrentFailed = true; torrentFailed = true;
} }
break;
} }
else
case ProcessedDecisionResult.Skipped:
{ {
_logger.Warn(ex, "Couldn't add report to download queue. " + remoteMovie); break;
} }
} }
} }
@ -113,6 +124,30 @@ public async Task<ProcessedDecisions> ProcessDecisions(List<DownloadDecision> de
return new ProcessedDecisions(grabbed, pending, rejected); return new ProcessedDecisions(grabbed, pending, rejected);
} }
public async Task<ProcessedDecisionResult> 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<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions) internal List<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions)
{ {
// Process both approved and temporarily rejected // Process both approved and temporarily rejected
@ -145,5 +180,38 @@ private void PreparePending(List<Tuple<DownloadDecision, PendingReleaseReason>>
queue.Add(Tuple.Create(report, reason)); queue.Add(Tuple.Create(report, reason));
pending.Add(report); pending.Add(report);
} }
private async Task<ProcessedDecisionResult> ProcessDecisionInternal(DownloadDecision decision, int? downloadClientId = null)
{
var remoteMovie = decision.RemoteMovie;
try
{
_logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteMovie.Release.Indexer, remoteMovie.Release.IndexerPriority);
await _downloadService.DownloadReport(remoteMovie, downloadClientId);
return ProcessedDecisionResult.Grabbed;
}
catch (ReleaseUnavailableException)
{
_logger.Warn("Failed to download release from indexer, no longer available. " + remoteMovie);
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. " + remoteMovie);
return ProcessedDecisionResult.Failed;
}
else
{
_logger.Warn(ex, "Couldn't add report to download queue. " + remoteMovie);
return ProcessedDecisionResult.Skipped;
}
}
}
} }
} }

View File

@ -0,0 +1,11 @@
namespace NzbDrone.Core.Download
{
public enum ProcessedDecisionResult
{
Grabbed,
Pending,
Rejected,
Failed,
Skipped
}
}

View File

@ -44,6 +44,7 @@ public ReleasePushController(IMakeDownloadDecision downloadDecisionMaker,
} }
[HttpPost] [HttpPost]
[Consumes("application/json")]
public ActionResult<List<ReleaseResource>> Create(ReleaseResource release) public ActionResult<List<ReleaseResource>> Create(ReleaseResource release)
{ {
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl); _logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl);
@ -56,22 +57,23 @@ public ActionResult<List<ReleaseResource>> Create(ReleaseResource release)
ResolveIndexer(info); ResolveIndexer(info);
List<DownloadDecision> decisions; DownloadDecision decision;
lock (PushLock) lock (PushLock)
{ {
decisions = _downloadDecisionMaker.GetRssDecision(new List<ReleaseInfo> { info }); var decisions = _downloadDecisionMaker.GetRssDecision(new List<ReleaseInfo> { info });
_downloadDecisionProcessor.ProcessDecisions(decisions).GetAwaiter().GetResult();
decision = decisions.FirstOrDefault();
_downloadDecisionProcessor.ProcessDecision(decision, release.DownloadClientId).GetAwaiter().GetResult();
} }
var firstDecision = decisions.FirstOrDefault(); if (decision?.RemoteMovie.ParsedMovieInfo == null)
if (firstDecision?.RemoteMovie.ParsedMovieInfo == null)
{ {
throw new ValidationException(new List<ValidationFailure> { new ValidationFailure("Title", "Unable to parse", release.Title) }); throw new ValidationException(new List<ValidationFailure> { new ValidationFailure("Title", "Unable to parse", release.Title) });
} }
return MapDecisions(new[] { firstDecision }); return MapDecisions(new[] { decision });
} }
private void ResolveIndexer(ReleaseInfo release) private void ResolveIndexer(ReleaseInfo release)