Fixed: Releases no longer available on the indexer should be removed from the pending queue.
fixes #679
This commit is contained in:
parent
b7e74bd5be
commit
20af2c8c0f
|
@ -8,6 +8,7 @@ using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Download.Clients;
|
using NzbDrone.Core.Download.Clients;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles;
|
||||||
|
@ -178,7 +179,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_an_empty_list_when_none_are_appproved()
|
public void should_return_an_empty_list_when_none_are_approved()
|
||||||
{
|
{
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
|
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
|
||||||
|
@ -263,5 +264,26 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteEpisode>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet)), Times.Once());
|
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteEpisode>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet)), Times.Once());
|
||||||
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteEpisode>(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent)), Times.Once());
|
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteEpisode>(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent)), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_add_to_rejected_if_release_unavailable_on_indexer()
|
||||||
|
{
|
||||||
|
var episodes = new List<Episode> { GetEpisode(1) };
|
||||||
|
var remoteEpisode = GetRemoteEpisode(episodes, new QualityModel(Quality.HDTV720p));
|
||||||
|
|
||||||
|
var decisions = new List<DownloadDecision>();
|
||||||
|
decisions.Add(new DownloadDecision(remoteEpisode));
|
||||||
|
|
||||||
|
Mocker.GetMock<IDownloadService>()
|
||||||
|
.Setup(s => s.DownloadReport(It.IsAny<RemoteEpisode>()))
|
||||||
|
.Throws(new ReleaseUnavailableException(remoteEpisode.Release, "That 404 Error is not just a Quirk"));
|
||||||
|
|
||||||
|
var result = Subject.ProcessDecisions(decisions);
|
||||||
|
|
||||||
|
result.Grabbed.Should().BeEmpty();
|
||||||
|
result.Rejected.Should().NotBeEmpty();
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,6 +180,21 @@ namespace NzbDrone.Core.Test.Download
|
||||||
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never());
|
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Download_report_should_not_trigger_indexer_backoff_on_indexer_404_error()
|
||||||
|
{
|
||||||
|
var mock = WithUsenetClient();
|
||||||
|
mock.Setup(s => s.Download(It.IsAny<RemoteEpisode>()))
|
||||||
|
.Callback<RemoteEpisode>(v => {
|
||||||
|
throw new ReleaseUnavailableException(v.Release, "Error", new WebException());
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Throws<ReleaseUnavailableException>(() => Subject.DownloadReport(_parseResult));
|
||||||
|
|
||||||
|
Mocker.GetMock<IIndexerStatusService>()
|
||||||
|
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_not_attempt_download_if_client_isnt_configured()
|
public void should_not_attempt_download_if_client_isnt_configured()
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||||
_remoteEpisode.Series = _series;
|
_remoteEpisode.Series = _series;
|
||||||
_remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo;
|
_remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo;
|
||||||
_remoteEpisode.Release = _release;
|
_remoteEpisode.Release = _release;
|
||||||
|
|
||||||
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
|
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
|
||||||
|
|
||||||
Mocker.GetMock<IPendingReleaseRepository>()
|
Mocker.GetMock<IPendingReleaseRepository>()
|
||||||
|
|
|
@ -75,6 +75,11 @@ namespace NzbDrone.Core.Download
|
||||||
_downloadClientStatusService.RecordSuccess(downloadClient.Definition.Id);
|
_downloadClientStatusService.RecordSuccess(downloadClient.Definition.Id);
|
||||||
_indexerStatusService.RecordSuccess(remoteEpisode.Release.IndexerId);
|
_indexerStatusService.RecordSuccess(remoteEpisode.Release.IndexerId);
|
||||||
}
|
}
|
||||||
|
catch (ReleaseUnavailableException)
|
||||||
|
{
|
||||||
|
_logger.Trace("Release {0} no longer available on indexer.", remoteEpisode);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch (ReleaseDownloadException ex)
|
catch (ReleaseDownloadException ex)
|
||||||
{
|
{
|
||||||
var http429 = ex.InnerException as TooManyRequestsException;
|
var http429 = ex.InnerException as TooManyRequestsException;
|
||||||
|
|
|
@ -6,6 +6,7 @@ using NLog;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download.Clients;
|
using NzbDrone.Core.Download.Clients;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download
|
namespace NzbDrone.Core.Download
|
||||||
|
@ -40,6 +41,7 @@ namespace NzbDrone.Core.Download
|
||||||
var grabbed = new List<DownloadDecision>();
|
var grabbed = new List<DownloadDecision>();
|
||||||
var pending = new List<DownloadDecision>();
|
var pending = new List<DownloadDecision>();
|
||||||
var failed = new List<DownloadDecision>();
|
var failed = new List<DownloadDecision>();
|
||||||
|
var rejected = decisions.Where(d => d.Rejected).ToList();
|
||||||
|
|
||||||
var usenetFailed = false;
|
var usenetFailed = false;
|
||||||
var torrentFailed = false;
|
var torrentFailed = false;
|
||||||
|
@ -74,6 +76,11 @@ namespace NzbDrone.Core.Download
|
||||||
_downloadService.DownloadReport(remoteEpisode);
|
_downloadService.DownloadReport(remoteEpisode);
|
||||||
grabbed.Add(report);
|
grabbed.Add(report);
|
||||||
}
|
}
|
||||||
|
catch (ReleaseUnavailableException)
|
||||||
|
{
|
||||||
|
_logger.Warn("Failed to download release from indexer, no longer available. " + remoteEpisode);
|
||||||
|
rejected.Add(report);
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException)
|
if (ex is DownloadClientUnavailableException || ex is DownloadClientAuthenticationException)
|
||||||
|
@ -99,7 +106,7 @@ namespace NzbDrone.Core.Download
|
||||||
|
|
||||||
pending.AddRange(ProcessFailedGrabs(grabbed, failed));
|
pending.AddRange(ProcessFailedGrabs(grabbed, failed));
|
||||||
|
|
||||||
return new ProcessedDecisions(grabbed, pending, decisions.Where(d => d.Rejected).ToList());
|
return new ProcessedDecisions(grabbed, pending, rejected);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal List<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions)
|
internal List<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions)
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Download
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_torrentFileInfoReader = torrentFileInfoReader;
|
_torrentFileInfoReader = torrentFileInfoReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||||
|
|
||||||
public virtual bool PreferTorrentFile => false;
|
public virtual bool PreferTorrentFile => false;
|
||||||
|
@ -61,7 +61,7 @@ namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
magnetUrl = torrentInfo.MagnetUrl;
|
magnetUrl = torrentInfo.MagnetUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferTorrentFile)
|
if (PreferTorrentFile)
|
||||||
{
|
{
|
||||||
if (torrentUrl.IsNotNullOrWhiteSpace())
|
if (torrentUrl.IsNotNullOrWhiteSpace())
|
||||||
|
@ -160,6 +160,12 @@ namespace NzbDrone.Core.Download
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
|
if (ex.Response.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Downloading torrent file for episode '{0}' failed since it no longer exists ({1})", remoteEpisode.Release.Title, torrentUrl);
|
||||||
|
throw new ReleaseUnavailableException(remoteEpisode.Release, "Downloading torrent failed", ex);
|
||||||
|
}
|
||||||
|
|
||||||
if ((int)ex.Response.StatusCode == 429)
|
if ((int)ex.Response.StatusCode == 429)
|
||||||
{
|
{
|
||||||
_logger.Error("API Grab Limit reached for {0}", torrentUrl);
|
_logger.Error("API Grab Limit reached for {0}", torrentUrl);
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
|
public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
|
||||||
|
|
||||||
protected abstract string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContent);
|
protected abstract string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContent);
|
||||||
|
@ -46,6 +46,12 @@ namespace NzbDrone.Core.Download
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
|
if (ex.Response.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Downloading nzb file for episode '{0}' failed since it no longer exists ({1})", remoteEpisode.Release.Title, url);
|
||||||
|
throw new ReleaseUnavailableException(remoteEpisode.Release, "Downloading torrent failed", ex);
|
||||||
|
}
|
||||||
|
|
||||||
if ((int)ex.Response.StatusCode == 429)
|
if ((int)ex.Response.StatusCode == 429)
|
||||||
{
|
{
|
||||||
_logger.Error("API Grab Limit reached for {0}", url);
|
_logger.Error("API Grab Limit reached for {0}", url);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Exceptions
|
||||||
|
{
|
||||||
|
public class ReleaseUnavailableException : ReleaseDownloadException
|
||||||
|
{
|
||||||
|
public ReleaseUnavailableException(ReleaseInfo release, string message, params object[] args)
|
||||||
|
: base(release, message, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReleaseUnavailableException(ReleaseInfo release, string message)
|
||||||
|
: base(release, message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReleaseUnavailableException(ReleaseInfo release, string message, Exception innerException, params object[] args)
|
||||||
|
: base(release, message, innerException, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReleaseUnavailableException(ReleaseInfo release, string message, Exception innerException)
|
||||||
|
: base(release, message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -539,6 +539,7 @@
|
||||||
<Compile Include="Exceptions\BadRequestException.cs" />
|
<Compile Include="Exceptions\BadRequestException.cs" />
|
||||||
<Compile Include="Exceptions\DownstreamException.cs" />
|
<Compile Include="Exceptions\DownstreamException.cs" />
|
||||||
<Compile Include="Exceptions\NzbDroneClientException.cs" />
|
<Compile Include="Exceptions\NzbDroneClientException.cs" />
|
||||||
|
<Compile Include="Exceptions\ReleaseUnavailableException.cs" />
|
||||||
<Compile Include="Exceptions\SeriesNotFoundException.cs" />
|
<Compile Include="Exceptions\SeriesNotFoundException.cs" />
|
||||||
<Compile Include="Exceptions\ReleaseDownloadException.cs" />
|
<Compile Include="Exceptions\ReleaseDownloadException.cs" />
|
||||||
<Compile Include="Exceptions\StatusCodeToExceptions.cs" />
|
<Compile Include="Exceptions\StatusCodeToExceptions.cs" />
|
||||||
|
|
Loading…
Reference in New Issue