New: Run missing root folder health check when an import is successful

pull/181/head
Qstick 7 years ago
parent 8ce1d4bcab
commit 0e7a22dc95

@ -1,5 +1,4 @@
using System; using System;
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.HealthCheck namespace NzbDrone.Core.HealthCheck
{ {
@ -7,10 +6,19 @@ namespace NzbDrone.Core.HealthCheck
public class CheckOnAttribute : Attribute public class CheckOnAttribute : Attribute
{ {
public Type EventType { get; set; } public Type EventType { get; set; }
public CheckOnCondition Condition { get; set; }
public CheckOnAttribute(Type eventType) public CheckOnAttribute(Type eventType, CheckOnCondition condition = CheckOnCondition.Always)
{ {
EventType = eventType; EventType = eventType;
Condition = condition;
} }
} }
public enum CheckOnCondition
{
Always,
FailedOnly,
SuccessfulOnly
}
} }

@ -1,5 +1,6 @@
using System.Linq; using System.Linq;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Music; using NzbDrone.Core.Music;
using NzbDrone.Core.Music.Events; using NzbDrone.Core.Music.Events;
@ -7,6 +8,8 @@ namespace NzbDrone.Core.HealthCheck.Checks
{ {
[CheckOn(typeof(ArtistDeletedEvent))] [CheckOn(typeof(ArtistDeletedEvent))]
[CheckOn(typeof(ArtistMovedEvent))] [CheckOn(typeof(ArtistMovedEvent))]
[CheckOn(typeof(TrackImportedEvent), CheckOnCondition.FailedOnly)]
[CheckOn(typeof(TrackImportFailedEvent), CheckOnCondition.SuccessfulOnly)]
public class RootFolderCheck : HealthCheckBase public class RootFolderCheck : HealthCheckBase
{ {
private readonly IArtistService _artistService; private readonly IArtistService _artistService;

@ -0,0 +1,14 @@
namespace NzbDrone.Core.HealthCheck
{
public class EventDrivenHealthCheck
{
public IProvideHealthCheck HealthCheck { get; set; }
public CheckOnCondition Condition { get; set; }
public EventDrivenHealthCheck(IProvideHealthCheck healthCheck, CheckOnCondition condition)
{
HealthCheck = healthCheck;
Condition = condition;
}
}
}

@ -29,7 +29,7 @@ namespace NzbDrone.Core.HealthCheck
private readonly IProvideHealthCheck[] _healthChecks; private readonly IProvideHealthCheck[] _healthChecks;
private readonly IProvideHealthCheck[] _startupHealthChecks; private readonly IProvideHealthCheck[] _startupHealthChecks;
private readonly IProvideHealthCheck[] _scheduledHealthChecks; private readonly IProvideHealthCheck[] _scheduledHealthChecks;
private readonly Dictionary<Type, IProvideHealthCheck[]> _eventDrivenHealthChecks; private readonly Dictionary<Type, EventDrivenHealthCheck[]> _eventDrivenHealthChecks;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly ICacheManager _cacheManager; private readonly ICacheManager _cacheManager;
private readonly Logger _logger; private readonly Logger _logger;
@ -58,10 +58,10 @@ namespace NzbDrone.Core.HealthCheck
return _healthCheckResults.Values.ToList(); return _healthCheckResults.Values.ToList();
} }
private Dictionary<Type, IProvideHealthCheck[]> GetEventDrivenHealthChecks() private Dictionary<Type, EventDrivenHealthCheck[]> GetEventDrivenHealthChecks()
{ {
return _healthChecks return _healthChecks
.SelectMany(h => h.GetType().GetAttributes<CheckOnAttribute>().Select(a => Tuple.Create(a.EventType, h))) .SelectMany(h => h.GetType().GetAttributes<CheckOnAttribute>().Select(a => Tuple.Create(a.EventType, new EventDrivenHealthCheck(h, a.Condition))))
.GroupBy(t => t.Item1, t => t.Item2) .GroupBy(t => t.Item1, t => t.Item2)
.ToDictionary(g => g.Key, g => g.ToArray()); .ToDictionary(g => g.Key, g => g.ToArray());
} }
@ -111,15 +111,42 @@ namespace NzbDrone.Core.HealthCheck
return; return;
} }
IProvideHealthCheck[] checks; EventDrivenHealthCheck[] checks;
if (!_eventDrivenHealthChecks.TryGetValue(message.GetType(), out checks)) if (!_eventDrivenHealthChecks.TryGetValue(message.GetType(), out checks))
{ {
return; return;
} }
var filteredChecks = new List<IProvideHealthCheck>();
var healthCheckResults = _healthCheckResults.Values.ToList();
foreach (var eventDrivenHealthCheck in checks)
{
if (eventDrivenHealthCheck.Condition == CheckOnCondition.Always)
{
filteredChecks.Add(eventDrivenHealthCheck.HealthCheck);
continue;
}
var healthCheckType = eventDrivenHealthCheck.HealthCheck.GetType();
if (eventDrivenHealthCheck.Condition == CheckOnCondition.FailedOnly &&
healthCheckResults.Any(r => r.Source == healthCheckType))
{
filteredChecks.Add(eventDrivenHealthCheck.HealthCheck);
continue;
}
if (eventDrivenHealthCheck.Condition == CheckOnCondition.SuccessfulOnly &&
healthCheckResults.None(r => r.Source == healthCheckType))
{
filteredChecks.Add(eventDrivenHealthCheck.HealthCheck);
}
}
// TODO: Add debounce // TODO: Add debounce
PerformHealthCheck(checks); PerformHealthCheck(filteredChecks.ToArray());
} }
} }
} }

@ -0,0 +1,29 @@
using System;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Download;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.Events
{
public class TrackImportFailedEvent : IEvent
{
public Exception Exception { get; set; }
public LocalTrack TrackInfo { get; }
public bool NewDownload { get; }
public string DownloadClient { get; }
public string DownloadId { get; }
public TrackImportFailedEvent(Exception exception, LocalTrack trackInfo, bool newDownload, DownloadClientItem downloadClientItem)
{
Exception = exception;
TrackInfo = trackInfo;
NewDownload = newDownload;
if (downloadClientItem != null)
{
DownloadClient = downloadClientItem.DownloadClient;
DownloadId = downloadClientItem.DownloadId;
}
}
}
}

@ -1,10 +1,10 @@
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.MediaFiles.TrackImport;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Music; using NzbDrone.Core.Music;
using NzbDrone.Core.Organizer; using NzbDrone.Core.Organizer;
@ -166,7 +166,7 @@ namespace NzbDrone.Core.MediaFiles
if (!_diskProvider.FolderExists(rootFolder)) if (!_diskProvider.FolderExists(rootFolder))
{ {
throw new TrackImport.RootFolderNotFoundException(string.Format("Root folder '{0}' was not found.", rootFolder)); throw new RootFolderNotFoundException(string.Format("Root folder '{0}' was not found.", rootFolder));
} }
var changed = false; var changed = false;

@ -131,6 +131,8 @@ namespace NzbDrone.Core.MediaFiles.TrackImport
catch (RootFolderNotFoundException e) catch (RootFolderNotFoundException e)
{ {
_logger.Warn(e, "Couldn't import track " + localTrack); _logger.Warn(e, "Couldn't import track " + localTrack);
_eventAggregator.PublishEvent(new TrackImportFailedEvent(e, localTrack, newDownload, downloadClientItem));
importResults.Add(new ImportResult(importDecision, "Failed to import track, Root folder missing.")); importResults.Add(new ImportResult(importDecision, "Failed to import track, Root folder missing."));
} }
catch (DestinationAlreadyExistsException e) catch (DestinationAlreadyExistsException e)

@ -469,6 +469,7 @@
<Compile Include="HealthCheck\Checks\ProxyCheck.cs" /> <Compile Include="HealthCheck\Checks\ProxyCheck.cs" />
<Compile Include="HealthCheck\Checks\RootFolderCheck.cs" /> <Compile Include="HealthCheck\Checks\RootFolderCheck.cs" />
<Compile Include="HealthCheck\Checks\UpdateCheck.cs" /> <Compile Include="HealthCheck\Checks\UpdateCheck.cs" />
<Compile Include="HealthCheck\EventDrivenHealthCheck.cs" />
<Compile Include="HealthCheck\HealthCheck.cs" /> <Compile Include="HealthCheck\HealthCheck.cs" />
<Compile Include="HealthCheck\HealthCheckBase.cs" /> <Compile Include="HealthCheck\HealthCheckBase.cs" />
<Compile Include="HealthCheck\HealthCheckCompleteEvent.cs" /> <Compile Include="HealthCheck\HealthCheckCompleteEvent.cs" />
@ -643,6 +644,7 @@
<Compile Include="MediaFiles\Commands\RenameArtistCommand.cs" /> <Compile Include="MediaFiles\Commands\RenameArtistCommand.cs" />
<Compile Include="MediaFiles\Events\TrackFileRenamedEvent.cs" /> <Compile Include="MediaFiles\Events\TrackFileRenamedEvent.cs" />
<Compile Include="MediaFiles\Events\TrackFolderCreatedEvent.cs" /> <Compile Include="MediaFiles\Events\TrackFolderCreatedEvent.cs" />
<Compile Include="MediaFiles\Events\TrackImportFailedEvent.cs" />
<Compile Include="MediaFiles\MediaFileDeletionService.cs" /> <Compile Include="MediaFiles\MediaFileDeletionService.cs" />
<Compile Include="MediaFiles\MediaInfo\MediaInfoFormatter.cs" /> <Compile Include="MediaFiles\MediaInfo\MediaInfoFormatter.cs" />
<Compile Include="MediaFiles\RenameTrackFilePreview.cs" /> <Compile Include="MediaFiles\RenameTrackFilePreview.cs" />

Loading…
Cancel
Save