Fixed: Various HealthCheck Improvements
- Align Radarr and Sonarr HealthChecks - Backport various Radarr changes - Add ProviderAddedEvent - Cleanup usings - Add HealthCheck Wiki Fragments - Add filterBlockedClients to Download Clients based on Radarr cae4faae61fe47ee6dacf334d8c4e4d483f5e5c8 Co-authored-by: Qstick <qstick@gmail.com>
This commit is contained in:
parent
f56d504816
commit
1c2359e66e
|
@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.Download
|
|||
_downloadClients = new List<IDownloadClient>();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(v => v.GetDownloadClients())
|
||||
.Setup(v => v.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(_downloadClients);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.HealthCheck.Checks;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.HealthCheck.Checks
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
public void should_return_warning_when_download_client_has_not_been_configured()
|
||||
{
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Setup(s => s.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(Array.Empty<IDownloadClient>());
|
||||
|
||||
Subject.Check().ShouldBeWarning();
|
||||
|
@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
.Throws<Exception>();
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Setup(s => s.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(new IDownloadClient[] { downloadClient.Object });
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
|
@ -46,7 +46,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
.Returns(new List<DownloadClientItem>());
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Setup(s => s.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(new IDownloadClient[] { downloadClient.Object });
|
||||
|
||||
Subject.Check().ShouldBeOk();
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
.Returns(_clientStatus);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Setup(s => s.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(new IDownloadClient[] { _downloadClient.Object });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
.Returns(_clientStatus);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Setup(s => s.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(new IDownloadClient[] { _downloadClient.Object });
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
|
|||
.Returns(_clientStatus);
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(s => s.GetDownloadClients())
|
||||
.Setup(s => s.GetDownloadClients(It.IsAny<bool>()))
|
||||
.Returns(new IDownloadClient[] { _downloadClient.Object });
|
||||
|
||||
Mocker.GetMock<IConfigService>()
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace NzbDrone.Core.Download
|
|||
public interface IProvideDownloadClient
|
||||
{
|
||||
IDownloadClient GetDownloadClient(DownloadProtocol downloadProtocol, int indexerId = 0);
|
||||
IEnumerable<IDownloadClient> GetDownloadClients();
|
||||
IEnumerable<IDownloadClient> GetDownloadClients(bool filterBlockedClients = false);
|
||||
IDownloadClient Get(int id);
|
||||
}
|
||||
|
||||
|
@ -86,14 +86,39 @@ namespace NzbDrone.Core.Download
|
|||
return provider;
|
||||
}
|
||||
|
||||
public IEnumerable<IDownloadClient> GetDownloadClients()
|
||||
public IEnumerable<IDownloadClient> GetDownloadClients(bool filterBlockedClients = false)
|
||||
{
|
||||
return _downloadClientFactory.GetAvailableProviders();
|
||||
var enabledClients = _downloadClientFactory.GetAvailableProviders();
|
||||
|
||||
if (filterBlockedClients)
|
||||
{
|
||||
return FilterBlockedIndexers(enabledClients).ToList();
|
||||
}
|
||||
|
||||
return enabledClients;
|
||||
}
|
||||
|
||||
public IDownloadClient Get(int id)
|
||||
{
|
||||
return _downloadClientFactory.GetAvailableProviders().Single(d => d.Definition.Id == id);
|
||||
}
|
||||
|
||||
private IEnumerable<IDownloadClient> FilterBlockedIndexers(IEnumerable<IDownloadClient> clients)
|
||||
{
|
||||
var blockedClients = _downloadClientStatusService.GetBlockedProviders().ToDictionary(v => v.ProviderId, v => v);
|
||||
|
||||
foreach (var client in clients)
|
||||
{
|
||||
DownloadClientStatus blockedClientStatus;
|
||||
|
||||
if (blockedClients.TryGetValue(client.Definition.Id, out blockedClientStatus))
|
||||
{
|
||||
_logger.Debug("Temporarily ignoring client {0} till {1} due to recent failures.", client.Definition.Name, blockedClientStatus.DisabledTill.Value.ToLocalTime());
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return client;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
|
@ -18,7 +17,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
if (_appFolderInfo.StartUpFolder.IsParentPath(_appFolderInfo.AppDataFolder) ||
|
||||
_appFolderInfo.StartUpFolder.PathEquals(_appFolderInfo.AppDataFolder))
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "Updating will not be possible to prevent deleting AppData on Update");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "Updating will not be possible to prevent deleting AppData on Update", "#updating-will-not-be-possible-to-prevent-deleting-appdata-on-update");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
|
|
|
@ -6,6 +6,7 @@ using NzbDrone.Core.ThingiProvider.Events;
|
|||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderAddedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderStatusChangedEvent<IDownloadClient>))]
|
||||
|
@ -26,7 +27,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
|
||||
if (!downloadClients.Any())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "No download client is available");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "No download client is available", "#no-download-client-is-available");
|
||||
}
|
||||
|
||||
foreach (var downloadClient in downloadClients)
|
||||
|
|
|
@ -12,6 +12,7 @@ using NzbDrone.Core.ThingiProvider.Events;
|
|||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderAddedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ModelEvent<RootFolder>))]
|
||||
|
@ -35,7 +36,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
public override HealthCheck Check()
|
||||
{
|
||||
// Only check clients not in failure status, those get another message
|
||||
var clients = _downloadClientProvider.GetDownloadClients();
|
||||
var clients = _downloadClientProvider.GetDownloadClients(true);
|
||||
var rootFolders = _rootFolderService.All();
|
||||
|
||||
foreach (var client in clients)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Download;
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.ImportLists;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IImportList>))]
|
||||
[CheckOn(typeof(SeriesDeletedEvent))]
|
||||
[CheckOn(typeof(SeriesMovedEvent))]
|
||||
[CheckOn(typeof(EpisodeImportedEvent), CheckOnCondition.FailedOnly)]
|
||||
|
@ -40,7 +41,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!_diskProvider.FolderExists(rootFolderPath))
|
||||
if (rootFolderPath.IsNullOrWhiteSpace() || !_diskProvider.FolderExists(rootFolderPath))
|
||||
{
|
||||
missingRootFolders.Add(rootFolderPath, new List<ImportListDefinition> { importList });
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
@ -30,7 +29,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
|
||||
if (active.Empty())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "All rss-capable indexers are temporarily unavailable due to recent indexer errors");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "All rss-capable indexers are temporarily unavailable due to recent indexer errors");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderAddedEvent<IIndexer>))]
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IIndexer>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IIndexer>))]
|
||||
[CheckOn(typeof(ProviderStatusChangedEvent<IIndexer>))]
|
||||
|
@ -23,21 +23,21 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
|
||||
if (automaticSearchEnabled.Empty())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "No indexers available with Automatic Search enabled, Sonarr will not provide any automatic search results");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "No indexers available with Automatic Search enabled, Sonarr will not provide any automatic search results", "#no-indexers-available-with-automatic-search-enabled-sonarr-will-not-provide-any-automatic-search-results");
|
||||
}
|
||||
|
||||
var interactiveSearchEnabled = _indexerFactory.InteractiveSearchEnabled(false);
|
||||
|
||||
if (interactiveSearchEnabled.Empty())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "No indexers available with Interactive Search enabled, Sonarr will not provide any interactive search results");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "No indexers available with Interactive Search enabled, Sonarr will not provide any interactive search results", "#no-indexers-available-with-interactive-search-enabled");
|
||||
}
|
||||
|
||||
var active = _indexerFactory.AutomaticSearchEnabled(true);
|
||||
|
||||
if (active.Empty())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "All search-capable indexers are temporarily unavailable due to recent indexer errors");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "All search-capable indexers are temporarily unavailable due to recent indexer errors", "#indexers-are-unavailable-due-to-failures");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
var addresses = Dns.GetHostAddresses(_configService.ProxyHostname);
|
||||
if (!addresses.Any())
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Failed to resolve the IP Address for the Configured Proxy Host {0}", _configService.ProxyHostname));
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format("Failed to resolve the IP Address for the Configured Proxy Host {0}", _configService.ProxyHostname), "#proxy-failed-resolve-ip");
|
||||
}
|
||||
|
||||
var request = _cloudRequestBuilder.Create()
|
||||
|
@ -49,13 +49,13 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
if (response.StatusCode == HttpStatusCode.BadRequest)
|
||||
{
|
||||
_logger.Error("Proxy Health Check failed: {0}", response.StatusCode);
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Failed to test proxy. StatusCode: {response.StatusCode}");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Failed to test proxy. StatusCode: {response.StatusCode}", "#proxy-failed-test");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Proxy Health Check failed");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Failed to test proxy: {request.Url}");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Failed to test proxy: {request.Url}", "#proxy-failed-test");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
|
||||
if (!_diskProvider.FolderWritable(recycleBin))
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Unable to write to configured recycling bin folder: {recycleBin}. Ensure this path exists and is writable by the user running Sonarr");
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Unable to write to configured recycling bin folder: {recycleBin}. Ensure this path exists and is writable by the user running Sonarr", "#cannot-write-recycle-bin");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
|
|
|
@ -13,13 +13,16 @@ using NzbDrone.Core.Download.Clients;
|
|||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.RemotePathMappings;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderAddedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ModelEvent<RemotePathMapping>))]
|
||||
[CheckOn(typeof(EpisodeImportFailedEvent), CheckOnCondition.SuccessfulOnly)]
|
||||
[CheckOn(typeof(SeriesImportedEvent), CheckOnCondition.SuccessfulOnly)]
|
||||
public class RemotePathMappingCheck : HealthCheckBase, IProvideHealthCheck
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
|
@ -143,7 +146,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
// If the previous case did not match then the failure occured in DownloadedEpisodeImportService,
|
||||
// while trying to locate the files reported by the download client
|
||||
// Only check clients not in failure status, those get another message
|
||||
var client = _downloadClientProvider.GetDownloadClients().FirstOrDefault(x => x.Definition.Name == failureMessage.DownloadClientInfo.Name);
|
||||
var client = _downloadClientProvider.GetDownloadClients(true).FirstOrDefault(x => x.Definition.Name == failureMessage.DownloadClientInfo.Name);
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
|
|
|
@ -65,12 +65,9 @@ namespace NzbDrone.Core.HealthCheck.Checks
|
|||
}
|
||||
}
|
||||
|
||||
if (BuildInfo.BuildDateTime < DateTime.UtcNow.AddDays(-14))
|
||||
if (BuildInfo.BuildDateTime < DateTime.UtcNow.AddDays(-14) && _checkUpdateService.AvailableUpdate() != null)
|
||||
{
|
||||
if (_checkUpdateService.AvailableUpdate() != null)
|
||||
{
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "New update is available");
|
||||
}
|
||||
return new HealthCheck(GetType(), HealthCheckResult.Warning, "New update is available");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.ThingiProvider.Events
|
||||
{
|
||||
public class ProviderAddedEvent<TProvider> : IEvent
|
||||
{
|
||||
public ProviderDefinition Definition { get; private set; }
|
||||
|
||||
public ProviderAddedEvent(ProviderDefinition definition)
|
||||
{
|
||||
Definition = definition;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -110,8 +110,7 @@ namespace NzbDrone.Core.ThingiProvider
|
|||
public virtual TProviderDefinition Create(TProviderDefinition definition)
|
||||
{
|
||||
var result = _providerRepository.Insert(definition);
|
||||
_eventAggregator.PublishEvent(new ProviderUpdatedEvent<TProvider>(result));
|
||||
|
||||
_eventAggregator.PublishEvent(new ProviderAddedEvent<TProvider>(definition));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue