Allow to override download client

Towards #3494
This commit is contained in:
Bogdan 2024-01-13 00:27:53 +02:00
parent d537d79f75
commit 71608897b7
7 changed files with 35 additions and 30 deletions

View File

@ -127,7 +127,7 @@ namespace Lidarr.Api.V1.Indexers
throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse albums in the release"); throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse albums in the release");
} }
await _downloadService.DownloadReport(remoteAlbum); await _downloadService.DownloadReport(remoteAlbum, release.DownloadClientId);
} }
catch (ReleaseDownloadException ex) catch (ReleaseDownloadException ex)
{ {

View File

@ -60,6 +60,9 @@ namespace Lidarr.Api.V1.Indexers
// [JsonIgnore] // [JsonIgnore]
public int? AlbumId { get; set; } public int? AlbumId { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? DownloadClientId { get; set; }
} }
public static class ReleaseResourceMapper public static class ReleaseResourceMapper

View File

@ -30,7 +30,7 @@ namespace Lidarr.Api.V1.Queue
throw new NotFoundException(); throw new NotFoundException();
} }
await _downloadService.DownloadReport(pendingRelease.RemoteAlbum); await _downloadService.DownloadReport(pendingRelease.RemoteAlbum, null);
return new { }; return new { };
} }
@ -48,7 +48,7 @@ namespace Lidarr.Api.V1.Queue
throw new NotFoundException(); throw new NotFoundException();
} }
await _downloadService.DownloadReport(pendingRelease.RemoteAlbum); await _downloadService.DownloadReport(pendingRelease.RemoteAlbum, null);
} }
return new { }; return new { };

View File

@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
await Subject.ProcessDecisions(decisions); await Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>(), null), Times.Once());
} }
[Test] [Test]
@ -82,7 +82,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
await Subject.ProcessDecisions(decisions); await Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>(), null), Times.Once());
} }
[Test] [Test]
@ -101,7 +101,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum2)); decisions.Add(new DownloadDecision(remoteAlbum2));
await Subject.ProcessDecisions(decisions); await Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>(), null), Times.Once());
} }
[Test] [Test]
@ -172,7 +172,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
var decisions = new List<DownloadDecision>(); var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>())).Throws(new Exception()); Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>(), null)).Throws(new Exception());
var result = await Subject.ProcessDecisions(decisions); var result = await Subject.ProcessDecisions(decisions);
@ -201,7 +201,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary))); decisions.Add(new DownloadDecision(remoteAlbum, new Rejection("Failure!", RejectionType.Temporary)));
await Subject.ProcessDecisions(decisions); await Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Never()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>(), null), Times.Never());
} }
[Test] [Test]
@ -242,11 +242,11 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>())) Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>(), null))
.Throws(new DownloadClientUnavailableException("Download client failed")); .Throws(new DownloadClientUnavailableException("Download client failed"));
await Subject.ProcessDecisions(decisions); await Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteAlbum>(), null), Times.Once());
} }
[Test] [Test]
@ -260,12 +260,12 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
decisions.Add(new DownloadDecision(remoteAlbum2)); decisions.Add(new DownloadDecision(remoteAlbum2));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.Is<RemoteAlbum>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet))) Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.Is<RemoteAlbum>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet), null))
.Throws(new DownloadClientUnavailableException("Download client failed")); .Throws(new DownloadClientUnavailableException("Download client failed"));
await Subject.ProcessDecisions(decisions); await Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteAlbum>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet)), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteAlbum>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet), null), Times.Once());
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteAlbum>(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent)), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteAlbum>(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent), null), Times.Once());
} }
[Test] [Test]
@ -278,7 +278,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteAlbum)); decisions.Add(new DownloadDecision(remoteAlbum));
Mocker.GetMock<IDownloadService>() Mocker.GetMock<IDownloadService>()
.Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>())) .Setup(s => s.DownloadReport(It.IsAny<RemoteAlbum>(), null))
.Throws(new ReleaseUnavailableException(remoteAlbum.Release, "That 404 Error is not just a Quirk")); .Throws(new ReleaseUnavailableException(remoteAlbum.Release, "That 404 Error is not just a Quirk"));
var result = await Subject.ProcessDecisions(decisions); var result = await Subject.ProcessDecisions(decisions);

View File

@ -83,7 +83,7 @@ namespace NzbDrone.Core.Test.Download
var mock = WithUsenetClient(); var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>())); mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()));
await Subject.DownloadReport(_parseResult); await Subject.DownloadReport(_parseResult, null);
VerifyEventPublished<AlbumGrabbedEvent>(); VerifyEventPublished<AlbumGrabbedEvent>();
} }
@ -94,7 +94,7 @@ namespace NzbDrone.Core.Test.Download
var mock = WithUsenetClient(); var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>())); mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()));
await Subject.DownloadReport(_parseResult); await Subject.DownloadReport(_parseResult, null);
mock.Verify(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once()); mock.Verify(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once());
} }
@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.Download
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>())) mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()))
.Throws(new WebException()); .Throws(new WebException());
Assert.ThrowsAsync<WebException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<WebException>(async () => await Subject.DownloadReport(_parseResult, null));
VerifyEventNotPublished<AlbumGrabbedEvent>(); VerifyEventNotPublished<AlbumGrabbedEvent>();
} }
@ -121,7 +121,7 @@ namespace NzbDrone.Core.Test.Download
throw new ReleaseDownloadException(v.Release, "Error", new WebException()); throw new ReleaseDownloadException(v.Release, "Error", new WebException());
}); });
Assert.ThrowsAsync<ReleaseDownloadException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<ReleaseDownloadException>(async () => await Subject.DownloadReport(_parseResult, null));
Mocker.GetMock<IIndexerStatusService>() Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Once()); .Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Once());
@ -141,7 +141,7 @@ namespace NzbDrone.Core.Test.Download
throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response)); throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response));
}); });
Assert.ThrowsAsync<ReleaseDownloadException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<ReleaseDownloadException>(async () => await Subject.DownloadReport(_parseResult, null));
Mocker.GetMock<IIndexerStatusService>() Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), TimeSpan.FromMinutes(5.0)), Times.Once()); .Verify(v => v.RecordFailure(It.IsAny<int>(), TimeSpan.FromMinutes(5.0)), Times.Once());
@ -161,7 +161,7 @@ namespace NzbDrone.Core.Test.Download
throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response)); throw new ReleaseDownloadException(v.Release, "Error", new TooManyRequestsException(request, response));
}); });
Assert.ThrowsAsync<ReleaseDownloadException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<ReleaseDownloadException>(async () => await Subject.DownloadReport(_parseResult, null));
Mocker.GetMock<IIndexerStatusService>() Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), .Verify(v => v.RecordFailure(It.IsAny<int>(),
@ -175,7 +175,7 @@ namespace NzbDrone.Core.Test.Download
mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>())) mock.Setup(s => s.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()))
.Throws(new DownloadClientException("Some Error")); .Throws(new DownloadClientException("Some Error"));
Assert.ThrowsAsync<DownloadClientException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<DownloadClientException>(async () => await Subject.DownloadReport(_parseResult, null));
Mocker.GetMock<IIndexerStatusService>() Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never()); .Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never());
@ -191,7 +191,7 @@ namespace NzbDrone.Core.Test.Download
throw new ReleaseUnavailableException(v.Release, "Error", new WebException()); throw new ReleaseUnavailableException(v.Release, "Error", new WebException());
}); });
Assert.ThrowsAsync<ReleaseUnavailableException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<ReleaseUnavailableException>(async () => await Subject.DownloadReport(_parseResult, null));
Mocker.GetMock<IIndexerStatusService>() Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never()); .Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never());
@ -200,7 +200,7 @@ namespace NzbDrone.Core.Test.Download
[Test] [Test]
public void should_not_attempt_download_if_client_isnt_configured() public void should_not_attempt_download_if_client_isnt_configured()
{ {
Assert.ThrowsAsync<DownloadClientUnavailableException>(async () => await Subject.DownloadReport(_parseResult)); Assert.ThrowsAsync<DownloadClientUnavailableException>(async () => await Subject.DownloadReport(_parseResult, null));
Mocker.GetMock<IDownloadClient>().Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Never()); Mocker.GetMock<IDownloadClient>().Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Never());
VerifyEventNotPublished<AlbumGrabbedEvent>(); VerifyEventNotPublished<AlbumGrabbedEvent>();
@ -222,7 +222,7 @@ namespace NzbDrone.Core.Test.Download
} }
}); });
await Subject.DownloadReport(_parseResult); await Subject.DownloadReport(_parseResult, null);
Mocker.GetMock<IDownloadClientStatusService>().Verify(c => c.GetBlockedProviders(), Times.Never()); Mocker.GetMock<IDownloadClientStatusService>().Verify(c => c.GetBlockedProviders(), Times.Never());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once()); mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once());
@ -235,7 +235,7 @@ namespace NzbDrone.Core.Test.Download
var mockTorrent = WithTorrentClient(); var mockTorrent = WithTorrentClient();
var mockUsenet = WithUsenetClient(); var mockUsenet = WithUsenetClient();
await Subject.DownloadReport(_parseResult); await Subject.DownloadReport(_parseResult, null);
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Never()); mockTorrent.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Never());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once()); mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once());
@ -249,7 +249,7 @@ namespace NzbDrone.Core.Test.Download
_parseResult.Release.DownloadProtocol = DownloadProtocol.Torrent; _parseResult.Release.DownloadProtocol = DownloadProtocol.Torrent;
await Subject.DownloadReport(_parseResult); await Subject.DownloadReport(_parseResult, null);
mockTorrent.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once()); mockTorrent.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Once());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Never()); mockUsenet.Verify(c => c.Download(It.IsAny<RemoteAlbum>(), It.IsAny<IIndexer>()), Times.Never());

View File

@ -17,7 +17,7 @@ namespace NzbDrone.Core.Download
{ {
public interface IDownloadService public interface IDownloadService
{ {
Task DownloadReport(RemoteAlbum remoteAlbum); Task DownloadReport(RemoteAlbum remoteAlbum, int? downloadClientId);
} }
public class DownloadService : IDownloadService public class DownloadService : IDownloadService
@ -50,13 +50,15 @@ namespace NzbDrone.Core.Download
_logger = logger; _logger = logger;
} }
public async Task DownloadReport(RemoteAlbum remoteAlbum) public async Task DownloadReport(RemoteAlbum remoteAlbum, int? downloadClientId)
{ {
var filterBlockedClients = remoteAlbum.Release.PendingReleaseReason == PendingReleaseReason.DownloadClientUnavailable; var filterBlockedClients = remoteAlbum.Release.PendingReleaseReason == PendingReleaseReason.DownloadClientUnavailable;
var tags = remoteAlbum.Artist?.Tags; var tags = remoteAlbum.Artist?.Tags;
var downloadClient = _downloadClientProvider.GetDownloadClient(remoteAlbum.Release.DownloadProtocol, remoteAlbum.Release.IndexerId, filterBlockedClients, tags); var downloadClient = downloadClientId.HasValue
? _downloadClientProvider.Get(downloadClientId.Value)
: _downloadClientProvider.GetDownloadClient(remoteAlbum.Release.DownloadProtocol, remoteAlbum.Release.IndexerId, filterBlockedClients, tags);
await DownloadReport(remoteAlbum, downloadClient); await DownloadReport(remoteAlbum, downloadClient);
} }

View File

@ -76,7 +76,7 @@ namespace NzbDrone.Core.Download
try try
{ {
_logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteAlbum.Release.Indexer, remoteAlbum.Release.IndexerPriority); _logger.Trace("Grabbing from Indexer {0} at priority {1}.", remoteAlbum.Release.Indexer, remoteAlbum.Release.IndexerPriority);
await _downloadService.DownloadReport(remoteAlbum); await _downloadService.DownloadReport(remoteAlbum, null);
grabbed.Add(report); grabbed.Add(report);
} }
catch (ReleaseUnavailableException) catch (ReleaseUnavailableException)