Added Status refreshes to Download Monitoring Service and allow DownloadService to report success (but not failure).

Taloth Saldono 7 years ago
parent f335cc1af8
commit 4e10d30cf6

@ -57,13 +57,6 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{ {
Subject.Check().ShouldBeOk(); Subject.Check().ShouldBeOk();
} }
[Test]
public void should_not_return_error_when_indexer_failed_less_than_an_hour()
{
GivenIndexer(1, 0.1, 0.5);
Subject.Check().ShouldBeOk();
}
[Test] [Test]
public void should_return_warning_if_indexer_unavailable() public void should_return_warning_if_indexer_unavailable()

@ -41,21 +41,6 @@ namespace NzbDrone.Core.Test.IndexerTests
.Verify(v => v.Upsert(It.IsAny<IndexerStatus>()), Times.Never()); .Verify(v => v.Upsert(It.IsAny<IndexerStatus>()), Times.Never());
} }
[Test]
public void should_start_backoff_on_first_failure()
{
WithStatus(new IndexerStatus());
Subject.RecordFailure(1);
VerifyUpdate();
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Value.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(5), 500);
}
[Test] [Test]
public void should_cancel_backoff_on_success() public void should_cancel_backoff_on_success()
{ {
@ -78,20 +63,5 @@ namespace NzbDrone.Core.Test.IndexerTests
VerifyNoUpdate(); VerifyNoUpdate();
} }
[Test]
public void should_preserve_escalation_on_intermittent_success()
{
WithStatus(new IndexerStatus { MostRecentFailure = _epoch - TimeSpan.FromSeconds(4), EscalationLevel = 3 });
Subject.RecordSuccess(1);
Subject.RecordSuccess(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Value.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(15), 500);
}
} }
} }

@ -1,5 +1,7 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentValidation.Results;
using NLog; using NLog;
using NzbDrone.Common.Composition; using NzbDrone.Common.Composition;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@ -9,17 +11,24 @@ namespace NzbDrone.Core.Download
{ {
public interface IDownloadClientFactory : IProviderFactory<IDownloadClient, DownloadClientDefinition> public interface IDownloadClientFactory : IProviderFactory<IDownloadClient, DownloadClientDefinition>
{ {
List<IDownloadClient> DownloadHandlingEnabled(bool filterBlockedClients = true);
} }
public class DownloadClientFactory : ProviderFactory<IDownloadClient, DownloadClientDefinition>, IDownloadClientFactory public class DownloadClientFactory : ProviderFactory<IDownloadClient, DownloadClientDefinition>, IDownloadClientFactory
{ {
private readonly IDownloadClientRepository _providerRepository; private readonly IDownloadClientStatusService _downloadClientStatusService;
private readonly Logger _logger;
public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable<IDownloadClient> providers, IContainer container, IEventAggregator eventAggregator, Logger logger) public DownloadClientFactory(IDownloadClientStatusService downloadClientStatusService,
IDownloadClientRepository providerRepository,
IEnumerable<IDownloadClient> providers,
IContainer container,
IEventAggregator eventAggregator,
Logger logger)
: base(providerRepository, providers, container, eventAggregator, logger) : base(providerRepository, providers, container, eventAggregator, logger)
{ {
_providerRepository = providerRepository; _downloadClientStatusService = downloadClientStatusService;
_logger = logger;
} }
protected override List<DownloadClientDefinition> Active() protected override List<DownloadClientDefinition> Active()
@ -33,5 +42,46 @@ namespace NzbDrone.Core.Download
definition.Protocol = provider.Protocol; definition.Protocol = provider.Protocol;
} }
public List<IDownloadClient> DownloadHandlingEnabled(bool filterBlockedClients = true)
{
var enabledClients = GetAvailableProviders();
if (filterBlockedClients)
{
return FilterBlockedClients(enabledClients).ToList();
}
return enabledClients.ToList();
}
private IEnumerable<IDownloadClient> FilterBlockedClients(IEnumerable<IDownloadClient> clients)
{
var blockedIndexers = _downloadClientStatusService.GetBlockedProviders().ToDictionary(v => v.ProviderId, v => v);
foreach (var client in clients)
{
DownloadClientStatus downloadClientStatus;
if (blockedIndexers.TryGetValue(client.Definition.Id, out downloadClientStatus))
{
_logger.Debug("Temporarily ignoring download client {0} till {1} due to recent failures.", client.Definition.Name, downloadClientStatus.DisabledTill.Value.ToLocalTime());
continue;
}
yield return client;
}
}
public override ValidationResult Test(DownloadClientDefinition definition)
{
var result = base.Test(definition);
if (result == null && definition.Id != 0)
{
_downloadClientStatusService.RecordSuccess(definition.Id);
}
return result;
}
} }
} }

@ -27,19 +27,12 @@ namespace NzbDrone.Core.Download
public IEnumerable<IDownloadClient> GetDownloadClients() public IEnumerable<IDownloadClient> GetDownloadClients()
{ {
return _downloadClientFactory.GetAvailableProviders();//.Select(MapDownloadClient); return _downloadClientFactory.GetAvailableProviders();
} }
public IDownloadClient Get(int id) public IDownloadClient Get(int id)
{ {
return _downloadClientFactory.GetAvailableProviders().Single(d => d.Definition.Id == id); return _downloadClientFactory.GetAvailableProviders().Single(d => d.Definition.Id == id);
} }
public IDownloadClient MapDownloadClient(IDownloadClient downloadClient)
{
_downloadClientFactory.SetProviderCharacteristics(downloadClient, (DownloadClientDefinition)downloadClient.Definition);
return downloadClient;
}
} }
} }

@ -21,18 +21,21 @@ namespace NzbDrone.Core.Download
public class DownloadService : IDownloadService public class DownloadService : IDownloadService
{ {
private readonly IProvideDownloadClient _downloadClientProvider; private readonly IProvideDownloadClient _downloadClientProvider;
private readonly IDownloadClientStatusService _downloadClientStatusService;
private readonly IIndexerStatusService _indexerStatusService; private readonly IIndexerStatusService _indexerStatusService;
private readonly IRateLimitService _rateLimitService; private readonly IRateLimitService _rateLimitService;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger; private readonly Logger _logger;
public DownloadService(IProvideDownloadClient downloadClientProvider, public DownloadService(IProvideDownloadClient downloadClientProvider,
IDownloadClientStatusService downloadClientStatusService,
IIndexerStatusService indexerStatusService, IIndexerStatusService indexerStatusService,
IRateLimitService rateLimitService, IRateLimitService rateLimitService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
Logger logger) Logger logger)
{ {
_downloadClientProvider = downloadClientProvider; _downloadClientProvider = downloadClientProvider;
_downloadClientStatusService = downloadClientStatusService;
_indexerStatusService = indexerStatusService; _indexerStatusService = indexerStatusService;
_rateLimitService = rateLimitService; _rateLimitService = rateLimitService;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
@ -64,6 +67,7 @@ namespace NzbDrone.Core.Download
try try
{ {
downloadClientId = downloadClient.Download(remoteEpisode); downloadClientId = downloadClient.Download(remoteEpisode);
_downloadClientStatusService.RecordSuccess(downloadClient.Definition.Id);
_indexerStatusService.RecordSuccess(remoteEpisode.Release.IndexerId); _indexerStatusService.RecordSuccess(remoteEpisode.Release.IndexerId);
} }
catch (ReleaseDownloadException ex) catch (ReleaseDownloadException ex)

@ -15,7 +15,8 @@ namespace NzbDrone.Core.Download.TrackedDownloads
IHandle<EpisodeGrabbedEvent>, IHandle<EpisodeGrabbedEvent>,
IHandle<EpisodeImportedEvent> IHandle<EpisodeImportedEvent>
{ {
private readonly IProvideDownloadClient _downloadClientProvider; private readonly IDownloadClientStatusService _downloadClientStatusService;
private readonly IDownloadClientFactory _downloadClientFactory;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IManageCommandQueue _manageCommandQueue; private readonly IManageCommandQueue _manageCommandQueue;
private readonly IConfigService _configService; private readonly IConfigService _configService;
@ -25,7 +26,8 @@ namespace NzbDrone.Core.Download.TrackedDownloads
private readonly Logger _logger; private readonly Logger _logger;
private readonly Debouncer _refreshDebounce; private readonly Debouncer _refreshDebounce;
public DownloadMonitoringService(IProvideDownloadClient downloadClientProvider, public DownloadMonitoringService(IDownloadClientStatusService downloadClientStatusService,
IDownloadClientFactory downloadClientFactory,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IManageCommandQueue manageCommandQueue, IManageCommandQueue manageCommandQueue,
IConfigService configService, IConfigService configService,
@ -34,7 +36,8 @@ namespace NzbDrone.Core.Download.TrackedDownloads
ITrackedDownloadService trackedDownloadService, ITrackedDownloadService trackedDownloadService,
Logger logger) Logger logger)
{ {
_downloadClientProvider = downloadClientProvider; _downloadClientStatusService = downloadClientStatusService;
_downloadClientFactory = downloadClientFactory;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_manageCommandQueue = manageCommandQueue; _manageCommandQueue = manageCommandQueue;
_configService = configService; _configService = configService;
@ -56,7 +59,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
_refreshDebounce.Pause(); _refreshDebounce.Pause();
try try
{ {
var downloadClients = _downloadClientProvider.GetDownloadClients(); var downloadClients = _downloadClientFactory.DownloadHandlingEnabled();
var trackedDownloads = new List<TrackedDownload>(); var trackedDownloads = new List<TrackedDownload>();
@ -84,9 +87,12 @@ namespace NzbDrone.Core.Download.TrackedDownloads
try try
{ {
downloadClientHistory = downloadClient.GetItems().ToList(); downloadClientHistory = downloadClient.GetItems().ToList();
_downloadClientStatusService.RecordSuccess(downloadClient.Definition.Id);
} }
catch (Exception ex) catch (Exception ex)
{ {
_downloadClientStatusService.RecordFailure(downloadClient.Definition.Id);
_logger.Warn(ex, "Unable to retrieve queue and history items from " + downloadClient.Definition.Name); _logger.Warn(ex, "Unable to retrieve queue and history items from " + downloadClient.Definition.Name);
} }

@ -36,7 +36,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
_logger.Debug(ex, "Unable to communicate with {0}", downloadClient.Definition.Name); _logger.Debug(ex, "Unable to communicate with {0}", downloadClient.Definition.Name);
var message = $"Unable to communicate with {downloadClient.Definition.Name}."; var message = $"Unable to communicate with {downloadClient.Definition.Name}.";
return new HealthCheck(GetType(), HealthCheckResult.Error, $"{message} {ex.Message}"); return new HealthCheck(GetType(), HealthCheckResult.Error, $"{message} {ex.Message}", "#unable-to-communicate-with-download-client");
} }
} }

@ -23,7 +23,6 @@ namespace NzbDrone.Core.HealthCheck.Checks
i => i.Definition.Id, i => i.Definition.Id,
s => s.ProviderId, s => s.ProviderId,
(i, s) => new { Provider = i, Status = s }) (i, s) => new { Provider = i, Status = s })
.Where(v => (v.Status.MostRecentFailure - v.Status.InitialFailure) > TimeSpan.FromHours(1))
.ToList(); .ToList();
if (backOffProviders.Empty()) if (backOffProviders.Empty())

@ -35,7 +35,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
Status = v.GetStatus() Status = v.GetStatus()
}).ToList(); }).ToList();
} }
catch (DownloadClientException) catch (Exception)
{ {
// One or more download clients failed, assume the health is okay and verify later // One or more download clients failed, assume the health is okay and verify later
return new HealthCheck(GetType()); return new HealthCheck(GetType());

@ -23,7 +23,6 @@ namespace NzbDrone.Core.HealthCheck.Checks
i => i.Definition.Id, i => i.Definition.Id,
s => s.ProviderId, s => s.ProviderId,
(i, s) => new { Provider = i, Status = s }) (i, s) => new { Provider = i, Status = s })
.Where(v => (v.Status.MostRecentFailure - v.Status.InitialFailure) > TimeSpan.FromHours(1))
.ToList(); .ToList();
if (backOffProviders.Empty()) if (backOffProviders.Empty())

Loading…
Cancel
Save