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,
IIndexerStatusService indexerStatusService, IDownloadClientStatusService downloadClientStatusService,
IRateLimitService rateLimitService, IIndexerStatusService indexerStatusService,
IEventAggregator eventAggregator, IRateLimitService rateLimitService,
Logger logger) IEventAggregator eventAggregator,
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)
@ -92,4 +96,4 @@ namespace NzbDrone.Core.Download
_eventAggregator.PublishEvent(episodeGrabbedEvent); _eventAggregator.PublishEvent(episodeGrabbedEvent);
} }
} }
} }

@ -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,16 +26,18 @@ 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,
IEventAggregator eventAggregator, IDownloadClientFactory downloadClientFactory,
IManageCommandQueue manageCommandQueue, IEventAggregator eventAggregator,
IConfigService configService, IManageCommandQueue manageCommandQueue,
IFailedDownloadService failedDownloadService, IConfigService configService,
ICompletedDownloadService completedDownloadService, IFailedDownloadService failedDownloadService,
ITrackedDownloadService trackedDownloadService, ICompletedDownloadService completedDownloadService,
Logger logger) ITrackedDownloadService trackedDownloadService,
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