From a3961ffb69f42d9978b1185c84dc742482895e3a Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 17:51:54 -0700 Subject: [PATCH 001/131] Added CommandId to commands --- .../MessageAggregatorCommandTests.cs | 8 +++++- NzbDrone.Common/HashUtil.cs | 26 ++----------------- NzbDrone.Common/Messaging/ICommand.cs | 3 +++ NzbDrone.Common/Messaging/TestCommand.cs | 10 ++++--- .../Scene/UpdateSceneMappingCommand.cs | 8 ++++++ .../IndexerSearch/EpisodeSearchCommand.cs | 10 ++++++- .../IndexerSearch/SeasonSearchCommand.cs | 10 ++++++- .../IndexerSearch/SeriesSearchCommand.cs | 10 ++++++- NzbDrone.Core/Indexers/RssSyncCommand.cs | 9 ++++++- .../Commands/ClearLogCommand.cs | 10 ++++++- .../Commands/DeleteLogFilesCommand.cs | 10 ++++++- .../Commands/TrimLogCommand.cs | 10 ++++++- .../MediaFiles/Commands/CleanMediaFileDb.cs | 9 +++++++ .../Commands/CleanUpRecycleBinCommand.cs | 8 ++++++ .../Commands/DownloadedEpisodesScanCommand.cs | 5 ++++ .../Commands/RenameSeasonCommand.cs | 10 +++++++ .../Commands/RenameSeriesCommand.cs | 9 +++++++ .../Notifications/Email/TestEmailCommand.cs | 10 ++++++- .../Notifications/Growl/TestGrowlCommand.cs | 10 ++++++- .../Plex/TestPlexClientCommand.cs | 10 ++++++- .../Plex/TestPlexServerCommand.cs | 10 ++++++- .../Notifications/Prowl/TestProwlCommand.cs | 10 ++++++- .../Pushover/TestPushoverCommand.cs | 10 ++++++- .../Notifications/Xbmc/TestXbmcCommand.cs | 10 ++++++- .../Providers/UpdateXemMappingsCommand.cs | 7 ++++- .../Tv/Commands/RefreshSeriesCommand.cs | 12 ++++++++- .../Commands/ApplicationUpdateCommand.cs | 10 ++++++- 27 files changed, 218 insertions(+), 46 deletions(-) diff --git a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs index 1e450ae21..38ce954f3 100644 --- a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs +++ b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs @@ -76,17 +76,23 @@ public void broken_executor_should_throw_the_exception() public class CommandA : ICommand { + public String CommandId { get; set; } // ReSharper disable UnusedParameter.Local public CommandA(int id = 0) // ReSharper restore UnusedParameter.Local { - + CommandId = HashUtil.GenerateCommandId(); } } public class CommandB : ICommand { + public String CommandId { get; set; } + public CommandB() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Common/HashUtil.cs b/NzbDrone.Common/HashUtil.cs index 0a127ee63..5777cc724 100644 --- a/NzbDrone.Common/HashUtil.cs +++ b/NzbDrone.Common/HashUtil.cs @@ -34,31 +34,9 @@ public static string CalculateCrc(string input) return String.Format("{0:x8}", mCrc); } - public static string GenerateUserId() + public static string GenerateCommandId() { - return GenerateId("u"); - } - - public static string GenerateAppId() - { - return GenerateId("a"); - } - - public static string GenerateApiToken() - { - return Guid.NewGuid().ToString().Replace("-", ""); - } - - public static string GenerateSecurityToken(int length) - { - var byteSize = (length / 4) * 3; - - var linkBytes = new byte[byteSize]; - var rngCrypto = new RNGCryptoServiceProvider(); - rngCrypto.GetBytes(linkBytes); - var base64String = Convert.ToBase64String(linkBytes); - - return base64String; + return GenerateId("c"); } private static string GenerateId(string prefix) diff --git a/NzbDrone.Common/Messaging/ICommand.cs b/NzbDrone.Common/Messaging/ICommand.cs index d9f8049ba..005a84a68 100644 --- a/NzbDrone.Common/Messaging/ICommand.cs +++ b/NzbDrone.Common/Messaging/ICommand.cs @@ -1,6 +1,9 @@ +using System; + namespace NzbDrone.Common.Messaging { public interface ICommand : IMessage { + String CommandId { get; } } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/TestCommand.cs b/NzbDrone.Common/Messaging/TestCommand.cs index 1a54d5764..3ede823e7 100644 --- a/NzbDrone.Common/Messaging/TestCommand.cs +++ b/NzbDrone.Common/Messaging/TestCommand.cs @@ -1,13 +1,15 @@ -namespace NzbDrone.Common.Messaging +using System; + +namespace NzbDrone.Common.Messaging { public class TestCommand : ICommand { + public int Duration { get; set; } + public String CommandId { get; set; } + public TestCommand() { Duration = 4000; } - - public int Duration { get; set; } - } } \ No newline at end of file diff --git a/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs b/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs index 68356ab6e..965121626 100644 --- a/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs +++ b/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs @@ -1,8 +1,16 @@ +using System; +using NzbDrone.Common; using NzbDrone.Common.Messaging; namespace NzbDrone.Core.DataAugmentation.Scene { public class UpdateSceneMappingCommand : ICommand { + public String CommandId { get; set; } + + public UpdateSceneMappingCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs b/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs index b0dce2fd1..08d47672d 100644 --- a/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs +++ b/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs @@ -1,9 +1,17 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.IndexerSearch { public class EpisodeSearchCommand : ICommand { + public String CommandId { get; set; } public int EpisodeId { get; set; } + + public EpisodeSearchCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs b/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs index cf9a8ba3e..a27d98306 100644 --- a/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs +++ b/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs @@ -1,10 +1,18 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.IndexerSearch { public class SeasonSearchCommand : ICommand { + public String CommandId { get; set; } public int SeriesId { get; set; } public int SeasonNumber { get; set; } + + public SeasonSearchCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs b/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs index 4e309fde8..e9ade1e45 100644 --- a/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs +++ b/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs @@ -1,9 +1,17 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.IndexerSearch { public class SeriesSearchCommand : ICommand { + public String CommandId { get; set; } public int SeriesId { get; set; } + + public SeriesSearchCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Indexers/RssSyncCommand.cs b/NzbDrone.Core/Indexers/RssSyncCommand.cs index 04a7a123b..467a7b030 100644 --- a/NzbDrone.Core/Indexers/RssSyncCommand.cs +++ b/NzbDrone.Core/Indexers/RssSyncCommand.cs @@ -1,9 +1,16 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Indexers { public class RssSyncCommand : ICommand { + public String CommandId { get; set; } + public RssSyncCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs b/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs index 19776e76d..34e2812ba 100644 --- a/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs +++ b/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs @@ -1,8 +1,16 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Instrumentation.Commands { public class ClearLogCommand : ICommand { + public String CommandId { get; set; } + + public ClearLogCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs b/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs index 5d3228afb..ea16c67d0 100644 --- a/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs +++ b/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs @@ -1,8 +1,16 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Instrumentation.Commands { public class DeleteLogFilesCommand : ICommand { + public String CommandId { get; set; } + + public DeleteLogFilesCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs b/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs index c00b27020..8221814ba 100644 --- a/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs +++ b/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs @@ -1,8 +1,16 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Instrumentation.Commands { public class TrimLogCommand : ICommand { + public String CommandId { get; set; } + + public TrimLogCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs b/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs index b873dcc5f..42822aae6 100644 --- a/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs +++ b/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs @@ -1,13 +1,22 @@ +using System; +using NzbDrone.Common; using NzbDrone.Common.Messaging; namespace NzbDrone.Core.MediaFiles.Commands { public class CleanMediaFileDb : ICommand { + public String CommandId { get; set; } public int SeriesId { get; private set; } + public CleanMediaFileDb() + { + CommandId = HashUtil.GenerateCommandId(); + } + public CleanMediaFileDb(int seriesId) { + CommandId = HashUtil.GenerateCommandId(); SeriesId = seriesId; } } diff --git a/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs b/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs index b2d16f231..66cbc07a9 100644 --- a/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs @@ -1,8 +1,16 @@ +using System; +using NzbDrone.Common; using NzbDrone.Common.Messaging; namespace NzbDrone.Core.MediaFiles.Commands { public class CleanUpRecycleBinCommand : ICommand { + public String CommandId { get; set; } + + public CleanUpRecycleBinCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs b/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs index 0f03f2083..b0e52126a 100644 --- a/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs @@ -1,11 +1,16 @@ +using System; +using NzbDrone.Common; using NzbDrone.Common.Messaging; namespace NzbDrone.Core.MediaFiles.Commands { public class DownloadedEpisodesScanCommand : ICommand { + public String CommandId { get; set; } + public DownloadedEpisodesScanCommand() { + CommandId = HashUtil.GenerateCommandId(); } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs b/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs index 723c5d74b..894a1eb86 100644 --- a/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs @@ -1,3 +1,5 @@ +using System; +using NzbDrone.Common; using NzbDrone.Common.Messaging; namespace NzbDrone.Core.MediaFiles.Commands @@ -7,8 +9,16 @@ public class RenameSeasonCommand : ICommand public int SeriesId { get; private set; } public int SeasonNumber { get; private set; } + public String CommandId { get; set; } + + public RenameSeasonCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } + public RenameSeasonCommand(int seriesId, int seasonNumber) { + CommandId = HashUtil.GenerateCommandId(); SeriesId = seriesId; SeasonNumber = seasonNumber; } diff --git a/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs b/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs index 7716c43c0..954d92ff1 100644 --- a/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs @@ -1,13 +1,22 @@ +using System; +using NzbDrone.Common; using NzbDrone.Common.Messaging; namespace NzbDrone.Core.MediaFiles.Commands { public class RenameSeriesCommand : ICommand { + public String CommandId { get; set; } public int SeriesId { get; private set; } + public RenameSeriesCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } + public RenameSeriesCommand(int seriesId) { + CommandId = HashUtil.GenerateCommandId(); SeriesId = seriesId; } } diff --git a/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs b/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs index 258884788..4ee1133ed 100644 --- a/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs +++ b/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs @@ -1,9 +1,12 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Email { public class TestEmailCommand : ICommand { + public String CommandId { get; set; } public string Server { get; set; } public int Port { get; set; } public bool Ssl { get; set; } @@ -11,5 +14,10 @@ public class TestEmailCommand : ICommand public string Password { get; set; } public string From { get; set; } public string To { get; set; } + + public TestEmailCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs b/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs index 35890fff9..71453e252 100644 --- a/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs +++ b/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs @@ -1,11 +1,19 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Growl { public class TestGrowlCommand : ICommand { + public String CommandId { get; set; } public string Host { get; set; } public int Port { get; set; } public string Password { get; set; } + + public TestGrowlCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs b/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs index 6df162ab4..bf456754e 100644 --- a/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs +++ b/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs @@ -1,12 +1,20 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Plex { public class TestPlexClientCommand : ICommand { + public String CommandId { get; set; } public string Host { get; set; } public int Port { get; set; } public string Username { get; set; } public string Password { get; set; } + + public TestPlexClientCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs b/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs index 49089afea..3921890bb 100644 --- a/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs +++ b/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs @@ -1,10 +1,18 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Plex { public class TestPlexServerCommand : ICommand { + public String CommandId { get; set; } public string Host { get; set; } public int Port { get; set; } + + public TestPlexServerCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs b/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs index e58bf5a9c..e30fa4c6b 100644 --- a/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs +++ b/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs @@ -1,10 +1,18 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Prowl { public class TestProwlCommand : ICommand { + public String CommandId { get; set; } public string ApiKey { get; set; } public int Priority { get; set; } + + public TestProwlCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs b/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs index 31bc034f9..55c6aad8f 100644 --- a/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs +++ b/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs @@ -1,10 +1,18 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Pushover { public class TestPushoverCommand : ICommand { + public String CommandId { get; set; } public string UserKey { get; set; } public int Priority { get; set; } + + public TestPushoverCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs b/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs index 56eb75ee8..17b9d1f72 100644 --- a/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs +++ b/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs @@ -1,13 +1,21 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Notifications.Xbmc { public class TestXbmcCommand : ICommand { + public String CommandId { get; set; } public string Host { get; set; } public int Port { get; set; } public string Username { get; set; } public string Password { get; set; } public int DisplayTime { get; set; } + + public TestXbmcCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } diff --git a/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs b/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs index da4b4b53f..0660cff7b 100644 --- a/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs +++ b/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs @@ -1,13 +1,18 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Providers { public class UpdateXemMappingsCommand : ICommand { + public String CommandId { get; set; } public int? SeriesId { get; private set; } public UpdateXemMappingsCommand(int? seriesId) { + CommandId = HashUtil.GenerateCommandId(); + SeriesId = seriesId; } } diff --git a/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs b/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs index f38af963c..941ce42dd 100644 --- a/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs +++ b/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs @@ -1,13 +1,23 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Tv.Commands { public class RefreshSeriesCommand : ICommand { + public String CommandId { get; set; } public int? SeriesId { get; private set; } + public RefreshSeriesCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } + public RefreshSeriesCommand(int? seriesId) { + CommandId = HashUtil.GenerateCommandId(); + SeriesId = seriesId; } } diff --git a/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs b/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs index bbbf6a1f3..e7cfa0a9d 100644 --- a/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs +++ b/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs @@ -1,8 +1,16 @@ -using NzbDrone.Common.Messaging; +using System; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; namespace NzbDrone.Core.Update.Commands { public class ApplicationUpdateCommand : ICommand { + public String CommandId { get; set; } + + public ApplicationUpdateCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } } } \ No newline at end of file From a86c131761d6040fe8ed23be878bf7ec783f4247 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 17:54:26 -0700 Subject: [PATCH 002/131] Added CommandStartedEvent --- NzbDrone.Common/Messaging/CommandExecutedEvent.cs | 12 ++++++++++++ NzbDrone.Common/Messaging/CommandStartedEvent.cs | 4 ++-- NzbDrone.Common/Messaging/MessageAggregator.cs | 3 +-- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 NzbDrone.Common/Messaging/CommandExecutedEvent.cs diff --git a/NzbDrone.Common/Messaging/CommandExecutedEvent.cs b/NzbDrone.Common/Messaging/CommandExecutedEvent.cs new file mode 100644 index 000000000..3cb4e7f55 --- /dev/null +++ b/NzbDrone.Common/Messaging/CommandExecutedEvent.cs @@ -0,0 +1,12 @@ +namespace NzbDrone.Common.Messaging +{ + public class CommandExecutedEvent : IEvent + { + public ICommand Command { get; private set; } + + public CommandExecutedEvent(ICommand command) + { + Command = command; + } + } +} \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/CommandStartedEvent.cs b/NzbDrone.Common/Messaging/CommandStartedEvent.cs index 3cb4e7f55..8c1b4163d 100644 --- a/NzbDrone.Common/Messaging/CommandStartedEvent.cs +++ b/NzbDrone.Common/Messaging/CommandStartedEvent.cs @@ -1,10 +1,10 @@ namespace NzbDrone.Common.Messaging { - public class CommandExecutedEvent : IEvent + public class CommandStartedEvent : IEvent { public ICommand Command { get; private set; } - public CommandExecutedEvent(ICommand command) + public CommandStartedEvent(ICommand command) { Command = command; } diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index 725f84ccf..59c831b71 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -60,7 +60,6 @@ public void PublishEvent(TEvent @event) where TEvent : class ,IEvent } } - private static string GetEventName(Type eventType) { if (!eventType.IsGenericType) @@ -71,7 +70,6 @@ private static string GetEventName(Type eventType) return string.Format("{0}<{1}>", eventType.Name.Remove(eventType.Name.IndexOf('`')), eventType.GetGenericArguments()[0].Name); } - public void PublishCommand(TCommand command) where TCommand : class, ICommand { Ensure.That(() => command).IsNotNull(); @@ -88,6 +86,7 @@ public void PublishCommand(TCommand command) where TCommand : class, I try { + PublishEvent(new CommandStartedEvent(command)); handler.Execute(command); sw.Stop(); PublishEvent(new CommandCompletedEvent(command)); From c917cdc0ccd679b8767a81fcb9174ab5f450751c Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 23:51:42 -0700 Subject: [PATCH 003/131] Commands are stored in memory and prevents duplicate jobs --- NzbDrone.Api/Commands/CommandModule.cs | 12 ++- .../CommandEqualityComparerFixture.cs | 76 +++++++++++++++++++ .../NzbDrone.Common.Test.csproj | 1 + NzbDrone.Common/Cache/CacheManger.cs | 1 - .../Messaging/CommandEqualityComparer.cs | 44 +++++++++++ .../{ => Events}/CommandCompletedEvent.cs | 2 +- .../{ => Events}/CommandExecutedEvent.cs | 2 +- .../{ => Events}/CommandFailedEvent.cs | 2 +- .../{ => Events}/CommandStartedEvent.cs | 2 +- NzbDrone.Common/Messaging/ICommand.cs | 1 + .../Messaging/Manager/CommandManager.cs | 59 ++++++++++++++ .../Messaging/Manager/CommandManagerItem.cs | 29 +++++++ .../Messaging/MessageAggregator.cs | 12 ++- NzbDrone.Common/NzbDrone.Common.csproj | 10 ++- NzbDrone.Core/Jobs/TaskManager.cs | 1 + NzbDrone.Core/Providers/XemProvider.cs | 3 +- 16 files changed, 244 insertions(+), 13 deletions(-) create mode 100644 NzbDrone.Common.Test/MessagingTests/CommandEqualityComparerFixture.cs create mode 100644 NzbDrone.Common/Messaging/CommandEqualityComparer.cs rename NzbDrone.Common/Messaging/{ => Events}/CommandCompletedEvent.cs (82%) rename NzbDrone.Common/Messaging/{ => Events}/CommandExecutedEvent.cs (82%) rename NzbDrone.Common/Messaging/{ => Events}/CommandFailedEvent.cs (89%) rename NzbDrone.Common/Messaging/{ => Events}/CommandStartedEvent.cs (82%) create mode 100644 NzbDrone.Common/Messaging/Manager/CommandManager.cs create mode 100644 NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs index 371483cc3..beb6fe246 100644 --- a/NzbDrone.Api/Commands/CommandModule.cs +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -4,6 +4,7 @@ using NzbDrone.Api.Extensions; using NzbDrone.Common.Composition; using NzbDrone.Common.Messaging; +using NzbDrone.Common.Messaging.Manager; namespace NzbDrone.Api.Commands { @@ -11,14 +12,16 @@ public class CommandModule : NzbDroneRestModule { private readonly IMessageAggregator _messageAggregator; private readonly IContainer _container; + private readonly IManageCommands _commandManager; - public CommandModule(IMessageAggregator messageAggregator, IContainer container) + public CommandModule(IMessageAggregator messageAggregator, IContainer container, IManageCommands commandManager) { _messageAggregator = messageAggregator; _container = container; + _commandManager = commandManager; Post["/"] = x => RunCommand(ReadResourceFromRequest()); - + Get["/"] = x => GetAllCommands(); } private Response RunCommand(CommandResource resource) @@ -33,5 +36,10 @@ private Response RunCommand(CommandResource resource) return resource.AsResponse(HttpStatusCode.Created); } + + private Response GetAllCommands() + { + return _commandManager.Items.AsResponse(); + } } } \ No newline at end of file diff --git a/NzbDrone.Common.Test/MessagingTests/CommandEqualityComparerFixture.cs b/NzbDrone.Common.Test/MessagingTests/CommandEqualityComparerFixture.cs new file mode 100644 index 000000000..2b2deadea --- /dev/null +++ b/NzbDrone.Common.Test/MessagingTests/CommandEqualityComparerFixture.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.IndexerSearch; +using NzbDrone.Core.MediaFiles.Commands; + +namespace NzbDrone.Common.Test.MessagingTests +{ + [TestFixture] + public class CommandEqualityComparerFixture + { + [Test] + public void should_return_true_when_there_are_no_properties() + { + var command1 = new DownloadedEpisodesScanCommand(); + var command2 = new DownloadedEpisodesScanCommand(); + var comparer = new CommandEqualityComparer(); + + comparer.Equals(command1, command2).Should().BeTrue(); + } + + [Test] + public void should_return_true_when_single_property_matches() + { + var command1 = new EpisodeSearchCommand { EpisodeId = 1 }; + var command2 = new EpisodeSearchCommand { EpisodeId = 1 }; + var comparer = new CommandEqualityComparer(); + + comparer.Equals(command1, command2).Should().BeTrue(); + } + + [Test] + public void should_return_true_when_multiple_properties_match() + { + var command1 = new SeasonSearchCommand { SeriesId = 1, SeasonNumber = 1 }; + var command2 = new SeasonSearchCommand { SeriesId = 1, SeasonNumber = 1 }; + var comparer = new CommandEqualityComparer(); + + comparer.Equals(command1, command2).Should().BeTrue(); + } + + [Test] + public void should_return_false_when_single_property_doesnt_match() + { + var command1 = new EpisodeSearchCommand { EpisodeId = 1 }; + var command2 = new EpisodeSearchCommand { EpisodeId = 2 }; + var comparer = new CommandEqualityComparer(); + + comparer.Equals(command1, command2).Should().BeFalse(); + } + + [Test] + public void should_return_false_when_only_one_property_matches() + { + var command1 = new SeasonSearchCommand { SeriesId = 1, SeasonNumber = 1 }; + var command2 = new SeasonSearchCommand { SeriesId = 1, SeasonNumber = 2 }; + var comparer = new CommandEqualityComparer(); + + comparer.Equals(command1, command2).Should().BeFalse(); + } + + [Test] + public void should_return_false_when_no_properties_match() + { + var command1 = new SeasonSearchCommand { SeriesId = 1, SeasonNumber = 1 }; + var command2 = new SeasonSearchCommand { SeriesId = 2, SeasonNumber = 2 }; + var comparer = new CommandEqualityComparer(); + + comparer.Equals(command1, command2).Should().BeFalse(); + } + } +} diff --git a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj index 4c22a7aeb..8fd34cbf6 100644 --- a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj +++ b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj @@ -69,6 +69,7 @@ + diff --git a/NzbDrone.Common/Cache/CacheManger.cs b/NzbDrone.Common/Cache/CacheManger.cs index d264eeb40..b5da3047c 100644 --- a/NzbDrone.Common/Cache/CacheManger.cs +++ b/NzbDrone.Common/Cache/CacheManger.cs @@ -28,7 +28,6 @@ public ICached GetCache(Type host) return GetCache(host, host.FullName); } - public void Clear() { _cache.Clear(); diff --git a/NzbDrone.Common/Messaging/CommandEqualityComparer.cs b/NzbDrone.Common/Messaging/CommandEqualityComparer.cs new file mode 100644 index 000000000..390319704 --- /dev/null +++ b/NzbDrone.Common/Messaging/CommandEqualityComparer.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Common.EnvironmentInfo; + +namespace NzbDrone.Common.Messaging +{ + public class CommandEqualityComparer : IEqualityComparer + { + public bool Equals(ICommand x, ICommand y) + { + var xProperties = x.GetType().GetProperties(); + var yProperties = y.GetType().GetProperties(); + + foreach (var xProperty in xProperties) + { + if (xProperty.Name == "CommandId") + { + continue; + } + + var yProperty = yProperties.SingleOrDefault(p => p.Name == xProperty.Name); + + if (yProperty == null) + { + continue; + } + + if (!xProperty.GetValue(x, null).Equals(yProperty.GetValue(y, null))) + { + return false; + } + } + + return true; + } + + public int GetHashCode(ICommand obj) + { + return obj.CommandId.GetHashCode(); + } + } +} diff --git a/NzbDrone.Common/Messaging/CommandCompletedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs similarity index 82% rename from NzbDrone.Common/Messaging/CommandCompletedEvent.cs rename to NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs index 613800ae0..b65f25bf2 100644 --- a/NzbDrone.Common/Messaging/CommandCompletedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs @@ -1,4 +1,4 @@ -namespace NzbDrone.Common.Messaging +namespace NzbDrone.Common.Messaging.Events { public class CommandCompletedEvent : IEvent { diff --git a/NzbDrone.Common/Messaging/CommandExecutedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs similarity index 82% rename from NzbDrone.Common/Messaging/CommandExecutedEvent.cs rename to NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs index 3cb4e7f55..e5e9120b3 100644 --- a/NzbDrone.Common/Messaging/CommandExecutedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs @@ -1,4 +1,4 @@ -namespace NzbDrone.Common.Messaging +namespace NzbDrone.Common.Messaging.Events { public class CommandExecutedEvent : IEvent { diff --git a/NzbDrone.Common/Messaging/CommandFailedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs similarity index 89% rename from NzbDrone.Common/Messaging/CommandFailedEvent.cs rename to NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs index d33ab79f8..ef4934e41 100644 --- a/NzbDrone.Common/Messaging/CommandFailedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs @@ -1,6 +1,6 @@ using System; -namespace NzbDrone.Common.Messaging +namespace NzbDrone.Common.Messaging.Events { public class CommandFailedEvent : IEvent { diff --git a/NzbDrone.Common/Messaging/CommandStartedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs similarity index 82% rename from NzbDrone.Common/Messaging/CommandStartedEvent.cs rename to NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs index 8c1b4163d..762c9287c 100644 --- a/NzbDrone.Common/Messaging/CommandStartedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs @@ -1,4 +1,4 @@ -namespace NzbDrone.Common.Messaging +namespace NzbDrone.Common.Messaging.Events { public class CommandStartedEvent : IEvent { diff --git a/NzbDrone.Common/Messaging/ICommand.cs b/NzbDrone.Common/Messaging/ICommand.cs index 005a84a68..e93f1ccaa 100644 --- a/NzbDrone.Common/Messaging/ICommand.cs +++ b/NzbDrone.Common/Messaging/ICommand.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace NzbDrone.Common.Messaging { diff --git a/NzbDrone.Common/Messaging/Manager/CommandManager.cs b/NzbDrone.Common/Messaging/Manager/CommandManager.cs new file mode 100644 index 000000000..4666e9cae --- /dev/null +++ b/NzbDrone.Common/Messaging/Manager/CommandManager.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NzbDrone.Common.Cache; +using NzbDrone.Common.Messaging.Events; + +namespace NzbDrone.Common.Messaging.Manager +{ + public interface IManageCommands + { + ICollection Items { get; } + Boolean ExistingItem(ICommand command); + } + + public class CommandManager : IManageCommands, + IHandle, + IHandle, + IHandle + { + private readonly ICached _cache; + + public CommandManager(ICacheManger cacheManger) + { + _cache = cacheManger.GetCache(GetType()); + } + + public void Handle(CommandStartedEvent message) + { + _cache.Set(message.Command.CommandId, new CommandManagerItem(message.Command, CommandState.Running)); + } + + public void Handle(CommandCompletedEvent message) + { + _cache.Set(message.Command.CommandId, new CommandManagerItem(message.Command, CommandState.Completed)); + } + + public void Handle(CommandFailedEvent message) + { + _cache.Set(message.Command.CommandId, new CommandManagerItem(message.Command, CommandState.Failed)); + } + + public ICollection Items + { + get + { + return _cache.Values; + } + } + + public bool ExistingItem(ICommand command) + { + var running = Items.Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running); + + var result = running.Select(r => r.Command).Contains(command, new CommandEqualityComparer()); + + return result; + } + } +} diff --git a/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs b/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs new file mode 100644 index 000000000..95c099151 --- /dev/null +++ b/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs @@ -0,0 +1,29 @@ +using System; + +namespace NzbDrone.Common.Messaging.Manager +{ + public class CommandManagerItem + { + public String Type { get; set; } + public ICommand Command { get; set; } + public CommandState State { get; set; } + + public CommandManagerItem() + { + } + + public CommandManagerItem(ICommand command, CommandState state) + { + Type = command.GetType().FullName; + Command = command; + State = state; + } + } + + public enum CommandState + { + Running = 0, + Completed = 1, + Failed = 2 + } +} diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index 59c831b71..30f300a70 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -4,6 +4,8 @@ using System.Threading.Tasks; using NLog; using NzbDrone.Common.EnsureThat; +using NzbDrone.Common.Messaging.Events; +using NzbDrone.Common.Messaging.Manager; using NzbDrone.Common.Serializer; using NzbDrone.Common.TPL; @@ -13,12 +15,14 @@ public class MessageAggregator : IMessageAggregator { private readonly Logger _logger; private readonly IServiceFactory _serviceFactory; + private readonly IManageCommands _commandManager; private readonly TaskFactory _taskFactory; - public MessageAggregator(Logger logger, IServiceFactory serviceFactory) + public MessageAggregator(Logger logger, IServiceFactory serviceFactory, IManageCommands commandManager) { _logger = logger; _serviceFactory = serviceFactory; + _commandManager = commandManager; var scheduler = new LimitedConcurrencyLevelTaskScheduler(2); _taskFactory = new TaskFactory(scheduler); } @@ -86,6 +90,12 @@ public void PublishCommand(TCommand command) where TCommand : class, I try { + if (_commandManager.ExistingItem(command)) + { + _logger.Info("Command is already in progress: {0}", command.GetType().Name); + return; + } + PublishEvent(new CommandStartedEvent(command)); handler.Execute(command); sw.Stop(); diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index c1b17236f..105c14d22 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -92,6 +92,10 @@ + + + + @@ -105,9 +109,9 @@ - - - + + + diff --git a/NzbDrone.Core/Jobs/TaskManager.cs b/NzbDrone.Core/Jobs/TaskManager.cs index 4c82da90a..83b079769 100644 --- a/NzbDrone.Core/Jobs/TaskManager.cs +++ b/NzbDrone.Core/Jobs/TaskManager.cs @@ -3,6 +3,7 @@ using System.Linq; using NLog; using NzbDrone.Common.Messaging; +using NzbDrone.Common.Messaging.Events; using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration.Events; using NzbDrone.Core.Indexers; diff --git a/NzbDrone.Core/Providers/XemProvider.cs b/NzbDrone.Core/Providers/XemProvider.cs index 931793dfb..f9d86f85c 100644 --- a/NzbDrone.Core/Providers/XemProvider.cs +++ b/NzbDrone.Core/Providers/XemProvider.cs @@ -131,8 +131,7 @@ public void PerformUpdate(Series series) catch (Exception ex) { - //TODO: We should increase this back to warn when caching is in place - _logger.TraceException("Error updating scene numbering mappings for: " + series, ex); + _logger.ErrorException("Error updating scene numbering mappings for: " + series, ex); } } From bb103947a21cfbeb87fcc143add41cdef61983a4 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 28 Aug 2013 08:05:41 -0700 Subject: [PATCH 004/131] Type and Command have private setters --- NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs b/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs index 95c099151..ddfca397b 100644 --- a/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs +++ b/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs @@ -4,14 +4,10 @@ namespace NzbDrone.Common.Messaging.Manager { public class CommandManagerItem { - public String Type { get; set; } - public ICommand Command { get; set; } + public String Type { get; private set; } + public ICommand Command { get; private set; } public CommandState State { get; set; } - public CommandManagerItem() - { - } - public CommandManagerItem(ICommand command, CommandState state) { Type = command.GetType().FullName; From 3c632743a146d4c9b1a399cab8e3b64aad67e79d Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 28 Aug 2013 21:43:26 -0700 Subject: [PATCH 005/131] Better names, more info, not using events --- NzbDrone.Api/Commands/CommandModule.cs | 10 +-- .../Messaging/Manager/CommandManager.cs | 59 -------------- .../Messaging/MessageAggregator.cs | 20 +++-- .../Tracking/CommandTrackingService.cs | 78 +++++++++++++++++++ .../TrackedCommand.cs} | 10 ++- NzbDrone.Common/NzbDrone.Common.csproj | 4 +- 6 files changed, 107 insertions(+), 74 deletions(-) delete mode 100644 NzbDrone.Common/Messaging/Manager/CommandManager.cs create mode 100644 NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs rename NzbDrone.Common/Messaging/{Manager/CommandManagerItem.cs => Tracking/TrackedCommand.cs} (55%) diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs index beb6fe246..db15b223f 100644 --- a/NzbDrone.Api/Commands/CommandModule.cs +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -4,7 +4,7 @@ using NzbDrone.Api.Extensions; using NzbDrone.Common.Composition; using NzbDrone.Common.Messaging; -using NzbDrone.Common.Messaging.Manager; +using NzbDrone.Common.Messaging.Tracking; namespace NzbDrone.Api.Commands { @@ -12,13 +12,13 @@ public class CommandModule : NzbDroneRestModule { private readonly IMessageAggregator _messageAggregator; private readonly IContainer _container; - private readonly IManageCommands _commandManager; + private readonly ITrackCommands _trackCommands; - public CommandModule(IMessageAggregator messageAggregator, IContainer container, IManageCommands commandManager) + public CommandModule(IMessageAggregator messageAggregator, IContainer container, ITrackCommands trackCommands) { _messageAggregator = messageAggregator; _container = container; - _commandManager = commandManager; + _trackCommands = trackCommands; Post["/"] = x => RunCommand(ReadResourceFromRequest()); Get["/"] = x => GetAllCommands(); @@ -39,7 +39,7 @@ private Response RunCommand(CommandResource resource) private Response GetAllCommands() { - return _commandManager.Items.AsResponse(); + return _trackCommands.AllTracked.AsResponse(); } } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/Manager/CommandManager.cs b/NzbDrone.Common/Messaging/Manager/CommandManager.cs deleted file mode 100644 index 4666e9cae..000000000 --- a/NzbDrone.Common/Messaging/Manager/CommandManager.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NzbDrone.Common.Cache; -using NzbDrone.Common.Messaging.Events; - -namespace NzbDrone.Common.Messaging.Manager -{ - public interface IManageCommands - { - ICollection Items { get; } - Boolean ExistingItem(ICommand command); - } - - public class CommandManager : IManageCommands, - IHandle, - IHandle, - IHandle - { - private readonly ICached _cache; - - public CommandManager(ICacheManger cacheManger) - { - _cache = cacheManger.GetCache(GetType()); - } - - public void Handle(CommandStartedEvent message) - { - _cache.Set(message.Command.CommandId, new CommandManagerItem(message.Command, CommandState.Running)); - } - - public void Handle(CommandCompletedEvent message) - { - _cache.Set(message.Command.CommandId, new CommandManagerItem(message.Command, CommandState.Completed)); - } - - public void Handle(CommandFailedEvent message) - { - _cache.Set(message.Command.CommandId, new CommandManagerItem(message.Command, CommandState.Failed)); - } - - public ICollection Items - { - get - { - return _cache.Values; - } - } - - public bool ExistingItem(ICommand command) - { - var running = Items.Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running); - - var result = running.Select(r => r.Command).Contains(command, new CommandEqualityComparer()); - - return result; - } - } -} diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index 30f300a70..84d16012d 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -5,7 +5,7 @@ using NLog; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.Messaging.Events; -using NzbDrone.Common.Messaging.Manager; +using NzbDrone.Common.Messaging.Tracking; using NzbDrone.Common.Serializer; using NzbDrone.Common.TPL; @@ -15,14 +15,14 @@ public class MessageAggregator : IMessageAggregator { private readonly Logger _logger; private readonly IServiceFactory _serviceFactory; - private readonly IManageCommands _commandManager; + private readonly ITrackCommands _trackCommands; private readonly TaskFactory _taskFactory; - public MessageAggregator(Logger logger, IServiceFactory serviceFactory, IManageCommands commandManager) + public MessageAggregator(Logger logger, IServiceFactory serviceFactory, ITrackCommands trackCommands) { _logger = logger; _serviceFactory = serviceFactory; - _commandManager = commandManager; + _trackCommands = trackCommands; var scheduler = new LimitedConcurrencyLevelTaskScheduler(2); _taskFactory = new TaskFactory(scheduler); } @@ -87,10 +87,13 @@ public void PublishCommand(TCommand command) where TCommand : class, I _logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name); var sw = Stopwatch.StartNew(); + TrackedCommand queuedCommand = null; try { - if (_commandManager.ExistingItem(command)) + queuedCommand = _trackCommands.TrackIfNew(command); + + if (queuedCommand == null) { _logger.Info("Command is already in progress: {0}", command.GetType().Name); return; @@ -99,10 +102,17 @@ public void PublishCommand(TCommand command) where TCommand : class, I PublishEvent(new CommandStartedEvent(command)); handler.Execute(command); sw.Stop(); + + _trackCommands.Completed(queuedCommand, sw.Elapsed); PublishEvent(new CommandCompletedEvent(command)); } catch (Exception e) { + if (queuedCommand != null) + { + _trackCommands.Failed(queuedCommand, e); + } + PublishEvent(new CommandFailedEvent(command, e)); throw; } diff --git a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs new file mode 100644 index 000000000..29f0fc0de --- /dev/null +++ b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NzbDrone.Common.Cache; + +namespace NzbDrone.Common.Messaging.Tracking +{ + public interface ITrackCommands + { + TrackedCommand TrackIfNew(ICommand command); + TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime); + TrackedCommand Failed(TrackedCommand trackedCommand, Exception e); + ICollection AllTracked { get; } + Boolean ExistingCommand(ICommand command); + } + + public class TrackCommands : ITrackCommands + { + private readonly ICached _cache; + + public TrackCommands(ICacheManger cacheManger) + { + _cache = cacheManger.GetCache(GetType()); + } + + public TrackedCommand TrackIfNew(ICommand command) + { + if (ExistingCommand(command)) + { + return null; + } + + var trackedCommand = new TrackedCommand(command, CommandState.Running); + _cache.Set(command.CommandId, trackedCommand); + + return trackedCommand; + } + + public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime) + { + trackedCommand.StateChangeTime = DateTime.UtcNow; + trackedCommand.State = CommandState.Completed; + trackedCommand.Runtime = runtime; + + _cache.Set(trackedCommand.Command.CommandId, trackedCommand); + + return trackedCommand; + } + + public TrackedCommand Failed(TrackedCommand trackedCommand, Exception e) + { + trackedCommand.StateChangeTime = DateTime.UtcNow; + trackedCommand.State = CommandState.Failed; + trackedCommand.Exception = e; + + _cache.Set(trackedCommand.Command.CommandId, trackedCommand); + + return trackedCommand; + } + + public ICollection AllTracked + { + get + { + return _cache.Values; + } + } + + public bool ExistingCommand(ICommand command) + { + var running = AllTracked.Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running); + + var result = running.Select(r => r.Command).Contains(command, new CommandEqualityComparer()); + + return result; + } + } +} diff --git a/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs similarity index 55% rename from NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs rename to NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs index ddfca397b..41f983d13 100644 --- a/NzbDrone.Common/Messaging/Manager/CommandManagerItem.cs +++ b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs @@ -1,18 +1,22 @@ using System; -namespace NzbDrone.Common.Messaging.Manager +namespace NzbDrone.Common.Messaging.Tracking { - public class CommandManagerItem + public class TrackedCommand { public String Type { get; private set; } public ICommand Command { get; private set; } public CommandState State { get; set; } + public DateTime StateChangeTime { get; set; } + public TimeSpan Runtime { get; set; } + public Exception Exception { get; set; } - public CommandManagerItem(ICommand command, CommandState state) + public TrackedCommand(ICommand command, CommandState state) { Type = command.GetType().FullName; Command = command; State = state; + StateChangeTime = DateTime.UtcNow; } } diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index 105c14d22..12ed1b7a9 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -92,8 +92,8 @@ - - + + From 780e374122b3e8f76e25ce63742cf50dd7c40d0d Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 30 Aug 2013 09:18:12 -0700 Subject: [PATCH 006/131] Added ProgressMessaging through nlog --- NzbDrone.Api/NancyBootstrapper.cs | 5 +- .../Messaging/MessageAggregator.cs | 14 ++-- .../ParserTests/ParserFixture.cs | 1 + .../Lifecycle/ApplicationStartedEvent.cs | 1 - NzbDrone.Core/NzbDrone.Core.csproj | 3 + .../NewProgressMessageEvent.cs | 18 ++++ .../ProgressMessaging/ProgressMessage.cs | 14 ++++ .../ProgressMessagingTarget.cs | 82 +++++++++++++++++++ UI/Router.js | 2 +- 9 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 NzbDrone.Core/ProgressMessaging/NewProgressMessageEvent.cs create mode 100644 NzbDrone.Core/ProgressMessaging/ProgressMessage.cs create mode 100644 NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs diff --git a/NzbDrone.Api/NancyBootstrapper.cs b/NzbDrone.Api/NancyBootstrapper.cs index 5f65c80e2..ed1463a23 100644 --- a/NzbDrone.Api/NancyBootstrapper.cs +++ b/NzbDrone.Api/NancyBootstrapper.cs @@ -9,6 +9,7 @@ using NzbDrone.Common.Messaging; using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Lifecycle; +using NzbDrone.Core.ProgressMessaging; using TinyIoC; namespace NzbDrone.Api @@ -28,14 +29,12 @@ protected override void ApplicationStartup(TinyIoCContainer container, IPipeline { _logger.Info("Starting NzbDrone API"); - RegisterPipelines(pipelines); container.Resolve().Register(); container.Resolve().Register(pipelines); container.Resolve().PublishEvent(new ApplicationStartedEvent()); - ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve().HandleException); } @@ -47,10 +46,8 @@ private void RegisterPipelines(IPipelines pipelines) { registerNancyPipeline.Register(pipelines); } - } - protected override TinyIoCContainer GetApplicationContainer() { return _tinyIoCContainer; diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index 84d16012d..0be1a0951 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -87,30 +87,32 @@ public void PublishCommand(TCommand command) where TCommand : class, I _logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name); var sw = Stopwatch.StartNew(); - TrackedCommand queuedCommand = null; + TrackedCommand trackedCommand = null; try { - queuedCommand = _trackCommands.TrackIfNew(command); + trackedCommand = _trackCommands.TrackIfNew(command); - if (queuedCommand == null) + if (trackedCommand == null) { _logger.Info("Command is already in progress: {0}", command.GetType().Name); return; } + MappedDiagnosticsContext.Set("CommandId", trackedCommand.Command.CommandId); + PublishEvent(new CommandStartedEvent(command)); handler.Execute(command); sw.Stop(); - _trackCommands.Completed(queuedCommand, sw.Elapsed); + _trackCommands.Completed(trackedCommand, sw.Elapsed); PublishEvent(new CommandCompletedEvent(command)); } catch (Exception e) { - if (queuedCommand != null) + if (trackedCommand != null) { - _trackCommands.Failed(queuedCommand, e); + _trackCommands.Failed(trackedCommand, e); } PublishEvent(new CommandFailedEvent(command, e)); diff --git a/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index 192ff7380..ac797bba8 100644 --- a/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -80,6 +80,7 @@ public class ParserFixture : CoreTest [TestCase("Top_Gear.19x06.720p_HDTV_x264-FoV", "Top Gear", 19, 6)] [TestCase("Portlandia.S03E10.Alexandra.720p.WEB-DL.AAC2.0.H.264-CROM.mkv", "Portlandia", 3, 10)] [TestCase("(Game of Thrones s03 e - \"Game of Thrones Season 3 Episode 10\"", "Game of Thrones", 3, 10)] + [TestCase("House.Hunters.International.S05E607.720p.hdtv.x264", "House.Hunters.International", 5, 607)] public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber) { var result = Parser.Parser.ParseTitle(postTitle); diff --git a/NzbDrone.Core/Lifecycle/ApplicationStartedEvent.cs b/NzbDrone.Core/Lifecycle/ApplicationStartedEvent.cs index 985986b05..f66622dd3 100644 --- a/NzbDrone.Core/Lifecycle/ApplicationStartedEvent.cs +++ b/NzbDrone.Core/Lifecycle/ApplicationStartedEvent.cs @@ -6,5 +6,4 @@ public class ApplicationStartedEvent : IEvent { } - } \ No newline at end of file diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 3f95a1ab6..6a13f8b82 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -219,6 +219,9 @@ + + + diff --git a/NzbDrone.Core/ProgressMessaging/NewProgressMessageEvent.cs b/NzbDrone.Core/ProgressMessaging/NewProgressMessageEvent.cs new file mode 100644 index 000000000..0b2905312 --- /dev/null +++ b/NzbDrone.Core/ProgressMessaging/NewProgressMessageEvent.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.ProgressMessaging +{ + public class NewProgressMessageEvent : IEvent + { + public ProgressMessage ProgressMessage { get; set; } + + public NewProgressMessageEvent(ProgressMessage progressMessage) + { + ProgressMessage = progressMessage; + } + } +} diff --git a/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs b/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs new file mode 100644 index 000000000..876087efb --- /dev/null +++ b/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.ProgressMessaging +{ + public class ProgressMessage + { + public DateTime Time { get; set; } + public String CommandId { get; set; } + public String Message { get; set; } + } +} diff --git a/NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs b/NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs new file mode 100644 index 000000000..247fa7686 --- /dev/null +++ b/NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs @@ -0,0 +1,82 @@ +using System; +using NLog.Config; +using NLog; +using NLog.Layouts; +using NLog.Targets; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.Lifecycle; + +namespace NzbDrone.Core.ProgressMessaging +{ + + public class ProgressMessagingTarget : TargetWithLayout, IHandle, IHandle + { + private readonly IMessageAggregator _messageAggregator; + public LoggingRule Rule { get; set; } + + public ProgressMessagingTarget(IMessageAggregator messageAggregator) + { + _messageAggregator = messageAggregator; + } + + public void Register() + { + Layout = new SimpleLayout("${callsite:className=false:fileName=false:includeSourcePath=false:methodName=true}"); + + Rule = new LoggingRule("*", this); + Rule.EnableLoggingForLevel(LogLevel.Info); + + LogManager.Configuration.AddTarget("ProgressMessagingLogger", this); + LogManager.Configuration.LoggingRules.Add(Rule); + LogManager.ConfigurationReloaded += OnLogManagerOnConfigurationReloaded; + LogManager.ReconfigExistingLoggers(); + } + + public void UnRegister() + { + LogManager.ConfigurationReloaded -= OnLogManagerOnConfigurationReloaded; + LogManager.Configuration.RemoveTarget("ProgressMessagingLogger"); + LogManager.Configuration.LoggingRules.Remove(Rule); + LogManager.ReconfigExistingLoggers(); + Dispose(); + } + + private void OnLogManagerOnConfigurationReloaded(object sender, LoggingConfigurationReloadedEventArgs args) + { + Register(); + } + + protected override void Write(LogEventInfo logEvent) + { + var commandId = MappedDiagnosticsContext.Get("CommandId"); + + if (String.IsNullOrWhiteSpace(commandId)) + { + return; + } + + var message = new ProgressMessage(); + message.Time = logEvent.TimeStamp; + message.CommandId = commandId; + message.Message = logEvent.FormattedMessage; + + _messageAggregator.PublishEvent(new NewProgressMessageEvent(message)); + } + + public void Handle(ApplicationStartedEvent message) + { + if (!LogManager.Configuration.LoggingRules.Contains(Rule)) + { + Register(); + } + } + + public void Handle(ApplicationShutdownRequested message) + { + if (LogManager.Configuration.LoggingRules.Contains(Rule)) + { + UnRegister(); + } + } + } +} \ No newline at end of file diff --git a/UI/Router.js b/UI/Router.js index 76513c471..984bf94ec 100644 --- a/UI/Router.js +++ b/UI/Router.js @@ -42,7 +42,7 @@ require( RouterBinder.bind(App.Router); App.navbarRegion.show(new NavbarView()); $('body').addClass('started'); - }) + }); }); return App.Router; From 56cd80d24a7ced98ea009af0b55f259a6ff92e9b Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 30 Aug 2013 10:27:17 -0700 Subject: [PATCH 007/131] TrackedCommands are cleaned up automatically TrackedCommandCleanupCommand is not tracked --- NzbDrone.Api/Commands/CommandModule.cs | 2 +- NzbDrone.Common/Cache/Cached.cs | 14 ++++++- NzbDrone.Common/Cache/ICached.cs | 1 + .../Tracking/CommandTrackingService.cs | 39 +++++++++++++------ .../Tracking/TrackedCommandCleanupCommand.cs | 17 ++++++++ NzbDrone.Common/NzbDrone.Common.csproj | 1 + NzbDrone.Core/Jobs/TaskManager.cs | 4 +- 7 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 NzbDrone.Common/Messaging/Tracking/TrackedCommandCleanupCommand.cs diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs index db15b223f..3f9a2e220 100644 --- a/NzbDrone.Api/Commands/CommandModule.cs +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -39,7 +39,7 @@ private Response RunCommand(CommandResource resource) private Response GetAllCommands() { - return _trackCommands.AllTracked.AsResponse(); + return _trackCommands.AllTracked().AsResponse(); } } } \ No newline at end of file diff --git a/NzbDrone.Common/Cache/Cached.cs b/NzbDrone.Common/Cache/Cached.cs index eef89f317..61d4733e4 100644 --- a/NzbDrone.Common/Cache/Cached.cs +++ b/NzbDrone.Common/Cache/Cached.cs @@ -61,6 +61,19 @@ public T Find(string key) return value.Object; } + public T Remove(string key) + { + CacheItem value; + _store.TryRemove(key, out value); + + if (value == null) + { + return default(T); + } + + return value.Object; + } + public T Get(string key, Func function, TimeSpan? lifeTime = null) { Ensure.That(() => key).IsNotNullOrWhiteSpace(); @@ -81,7 +94,6 @@ public T Get(string key, Func function, TimeSpan? lifeTime = null) return value; } - public void Clear() { _store.Clear(); diff --git a/NzbDrone.Common/Cache/ICached.cs b/NzbDrone.Common/Cache/ICached.cs index 3708b72af..7e68b395b 100644 --- a/NzbDrone.Common/Cache/ICached.cs +++ b/NzbDrone.Common/Cache/ICached.cs @@ -13,6 +13,7 @@ public interface ICached : ICached void Set(string key, T value, TimeSpan? lifetime = null); T Get(string key, Func function, TimeSpan? lifeTime = null); T Find(string key); + T Remove(string key); ICollection Values { get; } } diff --git a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs index 29f0fc0de..5962cabd2 100644 --- a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs +++ b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs @@ -10,11 +10,11 @@ public interface ITrackCommands TrackedCommand TrackIfNew(ICommand command); TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime); TrackedCommand Failed(TrackedCommand trackedCommand, Exception e); - ICollection AllTracked { get; } + List AllTracked(); Boolean ExistingCommand(ICommand command); } - public class TrackCommands : ITrackCommands + public class TrackCommands : ITrackCommands, IExecute { private readonly ICached _cache; @@ -31,7 +31,7 @@ public TrackedCommand TrackIfNew(ICommand command) } var trackedCommand = new TrackedCommand(command, CommandState.Running); - _cache.Set(command.CommandId, trackedCommand); + Store(trackedCommand); return trackedCommand; } @@ -42,7 +42,7 @@ public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime) trackedCommand.State = CommandState.Completed; trackedCommand.Runtime = runtime; - _cache.Set(trackedCommand.Command.CommandId, trackedCommand); + Store(trackedCommand); return trackedCommand; } @@ -53,26 +53,43 @@ public TrackedCommand Failed(TrackedCommand trackedCommand, Exception e) trackedCommand.State = CommandState.Failed; trackedCommand.Exception = e; - _cache.Set(trackedCommand.Command.CommandId, trackedCommand); + Store(trackedCommand); return trackedCommand; } - public ICollection AllTracked + public List AllTracked() { - get - { - return _cache.Values; - } + return _cache.Values.ToList(); } public bool ExistingCommand(ICommand command) { - var running = AllTracked.Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running); + var running = AllTracked().Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running); var result = running.Select(r => r.Command).Contains(command, new CommandEqualityComparer()); return result; } + + private void Store(TrackedCommand trackedCommand) + { + if (trackedCommand.Command.GetType() == typeof(TrackedCommandCleanupCommand)) + { + return; + } + + _cache.Set(trackedCommand.Command.CommandId, trackedCommand); + } + + public void Execute(TrackedCommandCleanupCommand message) + { + var old = AllTracked().Where(c => c.StateChangeTime < DateTime.UtcNow.AddMinutes(-15)); + + foreach (var trackedCommand in old) + { + _cache.Remove(trackedCommand.Command.CommandId); + } + } } } diff --git a/NzbDrone.Common/Messaging/Tracking/TrackedCommandCleanupCommand.cs b/NzbDrone.Common/Messaging/Tracking/TrackedCommandCleanupCommand.cs new file mode 100644 index 000000000..830ba7fb5 --- /dev/null +++ b/NzbDrone.Common/Messaging/Tracking/TrackedCommandCleanupCommand.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Common.Messaging.Tracking +{ + public class TrackedCommandCleanupCommand : ICommand + { + public string CommandId { get; private set; } + + public TrackedCommandCleanupCommand() + { + CommandId = HashUtil.GenerateCommandId(); + } + } +} diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index 12ed1b7a9..f980d4610 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -96,6 +96,7 @@ + diff --git a/NzbDrone.Core/Jobs/TaskManager.cs b/NzbDrone.Core/Jobs/TaskManager.cs index 83b079769..57a894629 100644 --- a/NzbDrone.Core/Jobs/TaskManager.cs +++ b/NzbDrone.Core/Jobs/TaskManager.cs @@ -4,6 +4,7 @@ using NLog; using NzbDrone.Common.Messaging; using NzbDrone.Common.Messaging.Events; +using NzbDrone.Common.Messaging.Tracking; using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration.Events; using NzbDrone.Core.Indexers; @@ -48,7 +49,8 @@ public void Handle(ApplicationStartedEvent message) new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName}, new ScheduledTask{ Interval = 1, TypeName = typeof(DownloadedEpisodesScanCommand).FullName}, new ScheduledTask{ Interval = 60, TypeName = typeof(ApplicationUpdateCommand).FullName}, - new ScheduledTask{ Interval = 1*60, TypeName = typeof(TrimLogCommand).FullName} + new ScheduledTask{ Interval = 1*60, TypeName = typeof(TrimLogCommand).FullName}, + new ScheduledTask{ Interval = 5, TypeName = typeof(TrackedCommandCleanupCommand).FullName} }; var currentTasks = _scheduledTaskRepository.All(); From 772ab3c92132196b63b15c92a262acc0bcce228f Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 15:14:44 -0700 Subject: [PATCH 008/131] Cahce.Remove is now void Added tests for Cache.Remove --- .../CacheTests/CachedFixture.cs | 17 +++++++++++++++++ NzbDrone.Common/Cache/Cached.cs | 9 +-------- NzbDrone.Common/Cache/ICached.cs | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/NzbDrone.Common.Test/CacheTests/CachedFixture.cs b/NzbDrone.Common.Test/CacheTests/CachedFixture.cs index 4a1cf9021..1d91558a6 100644 --- a/NzbDrone.Common.Test/CacheTests/CachedFixture.cs +++ b/NzbDrone.Common.Test/CacheTests/CachedFixture.cs @@ -48,6 +48,23 @@ public void should_be_able_to_update_key() _cachedString.Find("Key").Should().Be("New"); } + + [Test] + public void should_be_able_to_remove_key() + { + _cachedString.Set("Key", "Value"); + + _cachedString.Remove("Key"); + + _cachedString.Find("Key").Should().BeNull(); + } + + [Test] + public void should_be_able_to_remove_non_existing_key() + { + _cachedString.Remove("Key"); + } + [Test] public void should_store_null() { diff --git a/NzbDrone.Common/Cache/Cached.cs b/NzbDrone.Common/Cache/Cached.cs index 61d4733e4..7269a9a53 100644 --- a/NzbDrone.Common/Cache/Cached.cs +++ b/NzbDrone.Common/Cache/Cached.cs @@ -61,17 +61,10 @@ public T Find(string key) return value.Object; } - public T Remove(string key) + public void Remove(string key) { CacheItem value; _store.TryRemove(key, out value); - - if (value == null) - { - return default(T); - } - - return value.Object; } public T Get(string key, Func function, TimeSpan? lifeTime = null) diff --git a/NzbDrone.Common/Cache/ICached.cs b/NzbDrone.Common/Cache/ICached.cs index 7e68b395b..1c9e50812 100644 --- a/NzbDrone.Common/Cache/ICached.cs +++ b/NzbDrone.Common/Cache/ICached.cs @@ -13,7 +13,7 @@ public interface ICached : ICached void Set(string key, T value, TimeSpan? lifetime = null); T Get(string key, Func function, TimeSpan? lifeTime = null); T Find(string key); - T Remove(string key); + void Remove(string key); ICollection Values { get; } } From c96ba5efd33e87d17e50ab85e5aef34c4722d080 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 30 Aug 2013 20:08:19 -0700 Subject: [PATCH 009/131] Commands return immediately and signalr is used to control the UI --- NzbDrone.Api/Commands/CommandConnection.cs | 42 +++++ NzbDrone.Api/Commands/CommandModule.cs | 6 +- NzbDrone.Api/Extensions/ReqResExtensions.cs | 2 - NzbDrone.Api/NzbDrone.Api.csproj | 1 + .../MessageAggregatorCommandTests.cs | 4 +- .../Messaging/Events/CommandCompletedEvent.cs | 8 +- .../Messaging/Events/CommandExecutedEvent.cs | 8 +- .../Messaging/Events/CommandFailedEvent.cs | 5 +- .../Messaging/Events/CommandStartedEvent.cs | 8 +- .../Messaging/IMessageAggregator.cs | 8 +- .../Messaging/MessageAggregator.cs | 89 ++++++---- NzbDrone.Common/Messaging/TestCommand.cs | 2 +- .../Tracking/CommandTrackingService.cs | 40 ++++- .../Messaging/Tracking/ExistingCommand.cs | 19 +++ .../Messaging/Tracking/TrackedCommand.cs | 4 + NzbDrone.Common/NzbDrone.Common.csproj | 1 + .../Scene/UpdateSceneMappingCommand.cs | 2 +- .../IndexerSearch/EpisodeSearchCommand.cs | 2 +- .../IndexerSearch/SeasonSearchCommand.cs | 2 +- .../IndexerSearch/SeriesSearchCommand.cs | 2 +- NzbDrone.Core/Indexers/RssSyncCommand.cs | 2 +- .../Commands/ClearLogCommand.cs | 2 +- .../Commands/DeleteLogFilesCommand.cs | 2 +- .../Commands/TrimLogCommand.cs | 2 +- NzbDrone.Core/Jobs/TaskManager.cs | 2 +- .../MediaFiles/Commands/CleanMediaFileDb.cs | 2 +- .../Commands/CleanUpRecycleBinCommand.cs | 2 +- .../Commands/DownloadedEpisodesScanCommand.cs | 2 +- .../Commands/RenameSeasonCommand.cs | 6 +- .../Commands/RenameSeriesCommand.cs | 4 +- .../Notifications/Email/TestEmailCommand.cs | 2 +- .../Notifications/Growl/TestGrowlCommand.cs | 2 +- .../Plex/TestPlexClientCommand.cs | 2 +- .../Plex/TestPlexServerCommand.cs | 2 +- .../Notifications/Prowl/TestProwlCommand.cs | 2 +- .../Pushover/TestPushoverCommand.cs | 2 +- .../Notifications/Xbmc/TestXbmcCommand.cs | 2 +- .../Providers/UpdateXemMappingsCommand.cs | 5 +- .../Tv/Commands/RefreshSeriesCommand.cs | 4 +- .../Commands/ApplicationUpdateCommand.cs | 2 +- UI/Commands/CommandCollection.js | 17 ++ UI/Commands/CommandModel.js | 8 + UI/Episode/Search/Layout.js | 15 +- UI/Router.js | 3 +- UI/SeasonPass/SeriesLayout.js | 2 + UI/Series/Details/SeasonLayout.js | 18 +- UI/Series/Details/SeasonMenu/ItemView.js | 2 +- UI/Series/Details/SeriesDetailsLayout.js | 10 +- UI/Series/Index/SeriesIndexLayout.js | 3 - UI/Settings/Notifications/EditTemplate.html | 2 +- UI/Settings/Notifications/EditView.js | 45 ++--- UI/Shared/Actioneer.js | 158 ++++++++++++++---- UI/Shared/Messenger.js | 8 +- UI/Shared/Toolbar/Button/ButtonView.js | 77 ++------- UI/Shared/Toolbar/ToolbarLayout.js | 3 - 55 files changed, 439 insertions(+), 238 deletions(-) create mode 100644 NzbDrone.Api/Commands/CommandConnection.cs create mode 100644 NzbDrone.Common/Messaging/Tracking/ExistingCommand.cs create mode 100644 UI/Commands/CommandCollection.js create mode 100644 UI/Commands/CommandModel.js diff --git a/NzbDrone.Api/Commands/CommandConnection.cs b/NzbDrone.Api/Commands/CommandConnection.cs new file mode 100644 index 000000000..a09125734 --- /dev/null +++ b/NzbDrone.Api/Commands/CommandConnection.cs @@ -0,0 +1,42 @@ +using System; +using Microsoft.AspNet.SignalR; +using Microsoft.AspNet.SignalR.Infrastructure; +using NzbDrone.Api.SignalR; +using NzbDrone.Common.Messaging; +using NzbDrone.Common.Messaging.Events; +using NzbDrone.Common.Messaging.Tracking; + +namespace NzbDrone.Api.Commands +{ + public class CommandConnection : NzbDronePersistentConnection, + IHandleAsync, + IHandleAsync, + IHandle + { + public override string Resource + { + get { return "/Command"; } + } + + public void HandleAsync(CommandStartedEvent message) + { + BroadcastMessage(message.Command); + } + + public void HandleAsync(CommandCompletedEvent message) + { + BroadcastMessage(message.Command); + } + + public void Handle(CommandFailedEvent message) + { + BroadcastMessage(message.Command); + } + + private void BroadcastMessage(TrackedCommand trackedCommand) + { + var context = ((ConnectionManager)GlobalHost.ConnectionManager).GetConnection(GetType()); + context.Connection.Broadcast(trackedCommand); + } + } +} diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs index 3f9a2e220..8ad4a5475 100644 --- a/NzbDrone.Api/Commands/CommandModule.cs +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -2,6 +2,7 @@ using System.Linq; using Nancy; using NzbDrone.Api.Extensions; +using NzbDrone.Api.Mapping; using NzbDrone.Common.Composition; using NzbDrone.Common.Messaging; using NzbDrone.Common.Messaging.Tracking; @@ -32,9 +33,10 @@ private Response RunCommand(CommandResource resource) .Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase)); dynamic command = Request.Body.FromJson(commandType); - _messageAggregator.PublishCommand(command); - return resource.AsResponse(HttpStatusCode.Created); + var response = (TrackedCommand) _messageAggregator.PublishCommandAsync(command); + + return response.AsResponse(HttpStatusCode.Created); } private Response GetAllCommands() diff --git a/NzbDrone.Api/Extensions/ReqResExtensions.cs b/NzbDrone.Api/Extensions/ReqResExtensions.cs index fd9980347..1f1d89180 100644 --- a/NzbDrone.Api/Extensions/ReqResExtensions.cs +++ b/NzbDrone.Api/Extensions/ReqResExtensions.cs @@ -12,7 +12,6 @@ public static class ReqResExtensions { private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer(); - public static readonly string LastModified = BuildInfo.BuildDateTime.ToString("r"); public static T FromJson(this Stream body) where T : class, new() @@ -25,7 +24,6 @@ public static T FromJson(this Stream body, Type type) return (T)FromJson(body, type); } - public static object FromJson(this Stream body, Type type) { var reader = new StreamReader(body, true); diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj index d0a03bd17..fe4ffcc5a 100644 --- a/NzbDrone.Api/NzbDrone.Api.csproj +++ b/NzbDrone.Api/NzbDrone.Api.csproj @@ -83,6 +83,7 @@ + diff --git a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs index 38ce954f3..a0534a1ba 100644 --- a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs +++ b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs @@ -76,7 +76,7 @@ public void broken_executor_should_throw_the_exception() public class CommandA : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } // ReSharper disable UnusedParameter.Local public CommandA(int id = 0) // ReSharper restore UnusedParameter.Local @@ -87,7 +87,7 @@ public CommandA(int id = 0) public class CommandB : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public CommandB() { diff --git a/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs index b65f25bf2..2c1f4f312 100644 --- a/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs @@ -1,10 +1,12 @@ -namespace NzbDrone.Common.Messaging.Events +using NzbDrone.Common.Messaging.Tracking; + +namespace NzbDrone.Common.Messaging.Events { public class CommandCompletedEvent : IEvent { - public ICommand Command { get; private set; } + public TrackedCommand Command { get; private set; } - public CommandCompletedEvent(ICommand command) + public CommandCompletedEvent(TrackedCommand command) { Command = command; } diff --git a/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs index e5e9120b3..8ed4b5f75 100644 --- a/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs @@ -1,10 +1,12 @@ -namespace NzbDrone.Common.Messaging.Events +using NzbDrone.Common.Messaging.Tracking; + +namespace NzbDrone.Common.Messaging.Events { public class CommandExecutedEvent : IEvent { - public ICommand Command { get; private set; } + public TrackedCommand Command { get; private set; } - public CommandExecutedEvent(ICommand command) + public CommandExecutedEvent(TrackedCommand command) { Command = command; } diff --git a/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs index ef4934e41..f796f0f03 100644 --- a/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs @@ -1,13 +1,14 @@ using System; +using NzbDrone.Common.Messaging.Tracking; namespace NzbDrone.Common.Messaging.Events { public class CommandFailedEvent : IEvent { - public ICommand Command { get; private set; } + public TrackedCommand Command { get; private set; } public Exception Exception { get; private set; } - public CommandFailedEvent(ICommand command, Exception exception) + public CommandFailedEvent(TrackedCommand command, Exception exception) { Command = command; Exception = exception; diff --git a/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs index 762c9287c..14296c02a 100644 --- a/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs @@ -1,10 +1,12 @@ -namespace NzbDrone.Common.Messaging.Events +using NzbDrone.Common.Messaging.Tracking; + +namespace NzbDrone.Common.Messaging.Events { public class CommandStartedEvent : IEvent { - public ICommand Command { get; private set; } + public TrackedCommand Command { get; private set; } - public CommandStartedEvent(ICommand command) + public CommandStartedEvent(TrackedCommand command) { Command = command; } diff --git a/NzbDrone.Common/Messaging/IMessageAggregator.cs b/NzbDrone.Common/Messaging/IMessageAggregator.cs index 6de5ac3c8..9edd5b165 100644 --- a/NzbDrone.Common/Messaging/IMessageAggregator.cs +++ b/NzbDrone.Common/Messaging/IMessageAggregator.cs @@ -1,4 +1,6 @@ -namespace NzbDrone.Common.Messaging +using NzbDrone.Common.Messaging.Tracking; + +namespace NzbDrone.Common.Messaging { /// /// Enables loosely-coupled publication of events. @@ -7,6 +9,8 @@ public interface IMessageAggregator { void PublishEvent(TEvent @event) where TEvent : class, IEvent; void PublishCommand(TCommand command) where TCommand : class, ICommand; - void PublishCommand(string commandType); + void PublishCommand(string commandTypeName); + TrackedCommand PublishCommandAsync(TCommand command) where TCommand : class, ICommand; + TrackedCommand PublishCommandAsync(string commandTypeName); } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index 0be1a0951..b8ebd3690 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -78,61 +78,94 @@ public void PublishCommand(TCommand command) where TCommand : class, I { Ensure.That(() => command).IsNotNull(); - var handlerContract = typeof(IExecute<>).MakeGenericType(command.GetType()); + _logger.Trace("Publishing {0}", command.GetType().Name); + + var trackedCommand = _trackCommands.TrackIfNew(command); + + if (trackedCommand == null) + { + _logger.Info("Command is already in progress: {0}", command.GetType().Name); + return; + } + + ExecuteCommand(trackedCommand); + } + + public void PublishCommand(string commandTypeName) + { + dynamic command = GetCommand(commandTypeName); + PublishCommand(command); + } + + public TrackedCommand PublishCommandAsync(TCommand command) where TCommand : class, ICommand + { + Ensure.That(() => command).IsNotNull(); _logger.Trace("Publishing {0}", command.GetType().Name); + var existingCommand = _trackCommands.TrackNewOrGet(command); + + if (existingCommand.Existing) + { + _logger.Info("Command is already in progress: {0}", command.GetType().Name); + return existingCommand.TrackedCommand; + } + + _taskFactory.StartNew(() => ExecuteCommand(existingCommand.TrackedCommand) + , TaskCreationOptions.PreferFairness) + .LogExceptions(); + + return existingCommand.TrackedCommand; + } + + public TrackedCommand PublishCommandAsync(string commandTypeName) + { + dynamic command = GetCommand(commandTypeName); + return PublishCommandAsync(command); + } + + private dynamic GetCommand(string commandTypeName) + { + var commandType = _serviceFactory.GetImplementations(typeof(ICommand)) + .Single(c => c.FullName.Equals(commandTypeName, StringComparison.InvariantCultureIgnoreCase)); + + return Json.Deserialize("{}", commandType); + } + + private void ExecuteCommand(TrackedCommand trackedCommand) where TCommand : class, ICommand + { + var command = (TCommand)trackedCommand.Command; + + var handlerContract = typeof(IExecute<>).MakeGenericType(command.GetType()); var handler = (IExecute)_serviceFactory.Build(handlerContract); _logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name); var sw = Stopwatch.StartNew(); - TrackedCommand trackedCommand = null; try { - trackedCommand = _trackCommands.TrackIfNew(command); - - if (trackedCommand == null) - { - _logger.Info("Command is already in progress: {0}", command.GetType().Name); - return; - } - MappedDiagnosticsContext.Set("CommandId", trackedCommand.Command.CommandId); - PublishEvent(new CommandStartedEvent(command)); + PublishEvent(new CommandStartedEvent(trackedCommand)); handler.Execute(command); sw.Stop(); _trackCommands.Completed(trackedCommand, sw.Elapsed); - PublishEvent(new CommandCompletedEvent(command)); + PublishEvent(new CommandCompletedEvent(trackedCommand)); } catch (Exception e) { - if (trackedCommand != null) - { - _trackCommands.Failed(trackedCommand, e); - } - - PublishEvent(new CommandFailedEvent(command, e)); + _trackCommands.Failed(trackedCommand, e); + PublishEvent(new CommandFailedEvent(trackedCommand, e)); throw; } finally { - PublishEvent(new CommandExecutedEvent(command)); + PublishEvent(new CommandExecutedEvent(trackedCommand)); } _logger.Debug("{0} <- {1} [{2}]", command.GetType().Name, handler.GetType().Name, sw.Elapsed.ToString("")); } - - public void PublishCommand(string commandTypeName) - { - var commandType = _serviceFactory.GetImplementations(typeof(ICommand)) - .Single(c => c.FullName.Equals(commandTypeName, StringComparison.InvariantCultureIgnoreCase)); - - dynamic command = Json.Deserialize("{}", commandType); - PublishCommand(command); - } } } diff --git a/NzbDrone.Common/Messaging/TestCommand.cs b/NzbDrone.Common/Messaging/TestCommand.cs index 3ede823e7..c24a89780 100644 --- a/NzbDrone.Common/Messaging/TestCommand.cs +++ b/NzbDrone.Common/Messaging/TestCommand.cs @@ -5,7 +5,7 @@ namespace NzbDrone.Common.Messaging public class TestCommand : ICommand { public int Duration { get; set; } - public String CommandId { get; set; } + public String CommandId { get; private set; } public TestCommand() { diff --git a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs index 5962cabd2..2cb3b65ab 100644 --- a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs +++ b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Remoting; using NzbDrone.Common.Cache; namespace NzbDrone.Common.Messaging.Tracking @@ -8,10 +9,12 @@ namespace NzbDrone.Common.Messaging.Tracking public interface ITrackCommands { TrackedCommand TrackIfNew(ICommand command); + ExistingCommand TrackNewOrGet(ICommand command); TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime); TrackedCommand Failed(TrackedCommand trackedCommand, Exception e); List AllTracked(); Boolean ExistingCommand(ICommand command); + TrackedCommand FindExisting(ICommand command); } public class TrackCommands : ITrackCommands, IExecute @@ -36,6 +39,21 @@ public TrackedCommand TrackIfNew(ICommand command) return trackedCommand; } + public ExistingCommand TrackNewOrGet(ICommand command) + { + var trackedCommand = FindExisting(command); + + if (trackedCommand == null) + { + trackedCommand = new TrackedCommand(command, CommandState.Running); + Store(trackedCommand); + + return new ExistingCommand(false, trackedCommand); + } + + return new ExistingCommand(true, trackedCommand); + } + public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime) { trackedCommand.StateChangeTime = DateTime.UtcNow; @@ -65,11 +83,25 @@ public List AllTracked() public bool ExistingCommand(ICommand command) { - var running = AllTracked().Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running); + return FindExisting(command) != null; + } - var result = running.Select(r => r.Command).Contains(command, new CommandEqualityComparer()); + public TrackedCommand FindExisting(ICommand command) + { + var comparer = new CommandEqualityComparer(); + return Running(command.GetType()).SingleOrDefault(t => comparer.Equals(t.Command, command)); + } - return result; + private List Running(Type type = null) + { + var running = AllTracked().Where(i => i.State == CommandState.Running); + + if (type != null) + { + return running.Where(t => t.Type == type.FullName).ToList(); + } + + return running.ToList(); } private void Store(TrackedCommand trackedCommand) @@ -84,7 +116,7 @@ private void Store(TrackedCommand trackedCommand) public void Execute(TrackedCommandCleanupCommand message) { - var old = AllTracked().Where(c => c.StateChangeTime < DateTime.UtcNow.AddMinutes(-15)); + var old = AllTracked().Where(c => c.State != CommandState.Running && c.StateChangeTime < DateTime.UtcNow.AddMinutes(-5)); foreach (var trackedCommand in old) { diff --git a/NzbDrone.Common/Messaging/Tracking/ExistingCommand.cs b/NzbDrone.Common/Messaging/Tracking/ExistingCommand.cs new file mode 100644 index 000000000..7005585ef --- /dev/null +++ b/NzbDrone.Common/Messaging/Tracking/ExistingCommand.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Common.Messaging.Tracking +{ + public class ExistingCommand + { + public Boolean Existing { get; set; } + public TrackedCommand TrackedCommand { get; set; } + + public ExistingCommand(Boolean exisitng, TrackedCommand trackedCommand) + { + Existing = exisitng; + TrackedCommand = trackedCommand; + } + } +} diff --git a/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs index 41f983d13..cb00dd8c7 100644 --- a/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs +++ b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs @@ -4,6 +4,8 @@ namespace NzbDrone.Common.Messaging.Tracking { public class TrackedCommand { + public String Id { get; private set; } + public String Name { get; private set; } public String Type { get; private set; } public ICommand Command { get; private set; } public CommandState State { get; set; } @@ -13,6 +15,8 @@ public class TrackedCommand public TrackedCommand(ICommand command, CommandState state) { + Id = command.CommandId; + Name = command.GetType().Name; Type = command.GetType().FullName; Command = command; State = state; diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index f980d4610..75b255d08 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -93,6 +93,7 @@ + diff --git a/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs b/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs index 965121626..8b886d009 100644 --- a/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs +++ b/NzbDrone.Core/DataAugmentation/Scene/UpdateSceneMappingCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene { public class UpdateSceneMappingCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public UpdateSceneMappingCommand() { diff --git a/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs b/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs index 08d47672d..720955178 100644 --- a/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs +++ b/NzbDrone.Core/IndexerSearch/EpisodeSearchCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch { public class EpisodeSearchCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public int EpisodeId { get; set; } public EpisodeSearchCommand() diff --git a/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs b/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs index a27d98306..749fefae9 100644 --- a/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs +++ b/NzbDrone.Core/IndexerSearch/SeasonSearchCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch { public class SeasonSearchCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public int SeriesId { get; set; } public int SeasonNumber { get; set; } diff --git a/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs b/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs index e9ade1e45..8a8de6184 100644 --- a/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs +++ b/NzbDrone.Core/IndexerSearch/SeriesSearchCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch { public class SeriesSearchCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public int SeriesId { get; set; } public SeriesSearchCommand() diff --git a/NzbDrone.Core/Indexers/RssSyncCommand.cs b/NzbDrone.Core/Indexers/RssSyncCommand.cs index 467a7b030..0d073c977 100644 --- a/NzbDrone.Core/Indexers/RssSyncCommand.cs +++ b/NzbDrone.Core/Indexers/RssSyncCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Indexers { public class RssSyncCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public RssSyncCommand() { diff --git a/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs b/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs index 34e2812ba..cabaffcb5 100644 --- a/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs +++ b/NzbDrone.Core/Instrumentation/Commands/ClearLogCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Instrumentation.Commands { public class ClearLogCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public ClearLogCommand() { diff --git a/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs b/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs index ea16c67d0..8ae4d03d1 100644 --- a/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs +++ b/NzbDrone.Core/Instrumentation/Commands/DeleteLogFilesCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Instrumentation.Commands { public class DeleteLogFilesCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public DeleteLogFilesCommand() { diff --git a/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs b/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs index 8221814ba..7e710f294 100644 --- a/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs +++ b/NzbDrone.Core/Instrumentation/Commands/TrimLogCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Instrumentation.Commands { public class TrimLogCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public TrimLogCommand() { diff --git a/NzbDrone.Core/Jobs/TaskManager.cs b/NzbDrone.Core/Jobs/TaskManager.cs index 57a894629..2f5314d1f 100644 --- a/NzbDrone.Core/Jobs/TaskManager.cs +++ b/NzbDrone.Core/Jobs/TaskManager.cs @@ -50,7 +50,7 @@ public void Handle(ApplicationStartedEvent message) new ScheduledTask{ Interval = 1, TypeName = typeof(DownloadedEpisodesScanCommand).FullName}, new ScheduledTask{ Interval = 60, TypeName = typeof(ApplicationUpdateCommand).FullName}, new ScheduledTask{ Interval = 1*60, TypeName = typeof(TrimLogCommand).FullName}, - new ScheduledTask{ Interval = 5, TypeName = typeof(TrackedCommandCleanupCommand).FullName} + new ScheduledTask{ Interval = 1, TypeName = typeof(TrackedCommandCleanupCommand).FullName} }; var currentTasks = _scheduledTaskRepository.All(); diff --git a/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs b/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs index 42822aae6..7a195685a 100644 --- a/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs +++ b/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.MediaFiles.Commands { public class CleanMediaFileDb : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public int SeriesId { get; private set; } public CleanMediaFileDb() diff --git a/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs b/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs index 66cbc07a9..ef27ad213 100644 --- a/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/CleanUpRecycleBinCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.MediaFiles.Commands { public class CleanUpRecycleBinCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public CleanUpRecycleBinCommand() { diff --git a/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs b/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs index b0e52126a..a6caf5bee 100644 --- a/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/DownloadedEpisodesScanCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.MediaFiles.Commands { public class DownloadedEpisodesScanCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public DownloadedEpisodesScanCommand() { diff --git a/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs b/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs index 894a1eb86..5a61e100a 100644 --- a/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/RenameSeasonCommand.cs @@ -6,10 +6,10 @@ namespace NzbDrone.Core.MediaFiles.Commands { public class RenameSeasonCommand : ICommand { - public int SeriesId { get; private set; } - public int SeasonNumber { get; private set; } + public int SeriesId { get; set; } + public int SeasonNumber { get; set; } - public String CommandId { get; set; } + public String CommandId { get; private set; } public RenameSeasonCommand() { diff --git a/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs b/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs index 954d92ff1..f7e99512f 100644 --- a/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs +++ b/NzbDrone.Core/MediaFiles/Commands/RenameSeriesCommand.cs @@ -6,8 +6,8 @@ namespace NzbDrone.Core.MediaFiles.Commands { public class RenameSeriesCommand : ICommand { - public String CommandId { get; set; } - public int SeriesId { get; private set; } + public String CommandId { get; private set; } + public int SeriesId { get; set; } public RenameSeriesCommand() { diff --git a/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs b/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs index 4ee1133ed..26bf91c94 100644 --- a/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs +++ b/NzbDrone.Core/Notifications/Email/TestEmailCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Email { public class TestEmailCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string Server { get; set; } public int Port { get; set; } public bool Ssl { get; set; } diff --git a/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs b/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs index 71453e252..8494e0d9d 100644 --- a/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs +++ b/NzbDrone.Core/Notifications/Growl/TestGrowlCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Growl { public class TestGrowlCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string Host { get; set; } public int Port { get; set; } public string Password { get; set; } diff --git a/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs b/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs index bf456754e..365add8a2 100644 --- a/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs +++ b/NzbDrone.Core/Notifications/Plex/TestPlexClientCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Plex { public class TestPlexClientCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string Host { get; set; } public int Port { get; set; } public string Username { get; set; } diff --git a/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs b/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs index 3921890bb..7306e5a10 100644 --- a/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs +++ b/NzbDrone.Core/Notifications/Plex/TestPlexServerCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Plex { public class TestPlexServerCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string Host { get; set; } public int Port { get; set; } diff --git a/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs b/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs index e30fa4c6b..869123be0 100644 --- a/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs +++ b/NzbDrone.Core/Notifications/Prowl/TestProwlCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Prowl { public class TestProwlCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string ApiKey { get; set; } public int Priority { get; set; } diff --git a/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs b/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs index 55c6aad8f..0c6ec8912 100644 --- a/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs +++ b/NzbDrone.Core/Notifications/Pushover/TestPushoverCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Pushover { public class TestPushoverCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string UserKey { get; set; } public int Priority { get; set; } diff --git a/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs b/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs index 17b9d1f72..02c594e8d 100644 --- a/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs +++ b/NzbDrone.Core/Notifications/Xbmc/TestXbmcCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Xbmc { public class TestXbmcCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public string Host { get; set; } public int Port { get; set; } public string Username { get; set; } diff --git a/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs b/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs index 0660cff7b..0dd28372d 100644 --- a/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs +++ b/NzbDrone.Core/Providers/UpdateXemMappingsCommand.cs @@ -6,13 +6,12 @@ namespace NzbDrone.Core.Providers { public class UpdateXemMappingsCommand : ICommand { - public String CommandId { get; set; } - public int? SeriesId { get; private set; } + public String CommandId { get; private set; } + public int? SeriesId { get; set; } public UpdateXemMappingsCommand(int? seriesId) { CommandId = HashUtil.GenerateCommandId(); - SeriesId = seriesId; } } diff --git a/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs b/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs index 941ce42dd..a58fca783 100644 --- a/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs +++ b/NzbDrone.Core/Tv/Commands/RefreshSeriesCommand.cs @@ -6,8 +6,8 @@ namespace NzbDrone.Core.Tv.Commands { public class RefreshSeriesCommand : ICommand { - public String CommandId { get; set; } - public int? SeriesId { get; private set; } + public String CommandId { get; private set; } + public int? SeriesId { get; set; } public RefreshSeriesCommand() { diff --git a/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs b/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs index e7cfa0a9d..dd1b97d6b 100644 --- a/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs +++ b/NzbDrone.Core/Update/Commands/ApplicationUpdateCommand.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Update.Commands { public class ApplicationUpdateCommand : ICommand { - public String CommandId { get; set; } + public String CommandId { get; private set; } public ApplicationUpdateCommand() { diff --git a/UI/Commands/CommandCollection.js b/UI/Commands/CommandCollection.js new file mode 100644 index 000000000..72939381b --- /dev/null +++ b/UI/Commands/CommandCollection.js @@ -0,0 +1,17 @@ +'use strict'; +define( + [ + 'backbone', + 'Commands/CommandModel', + 'Mixins/backbone.signalr.mixin' + ], function (Backbone, CommandModel) { + + var CommandCollection = Backbone.Collection.extend({ + url : window.ApiRoot + '/command', + model: CommandModel + }); + + var collection = new CommandCollection().bindSignalR(); + + return collection; + }); diff --git a/UI/Commands/CommandModel.js b/UI/Commands/CommandModel.js new file mode 100644 index 000000000..33a6217c8 --- /dev/null +++ b/UI/Commands/CommandModel.js @@ -0,0 +1,8 @@ +'use strict'; +define( + [ + 'backbone' + ], function (Backbone) { + return Backbone.Model.extend({ + }); + }); diff --git a/UI/Episode/Search/Layout.js b/UI/Episode/Search/Layout.js index 15b89f79a..aa24febf5 100644 --- a/UI/Episode/Search/Layout.js +++ b/UI/Episode/Search/Layout.js @@ -9,9 +9,9 @@ define( 'Series/SeriesCollection', 'Shared/LoadingView', 'Shared/Messenger', - 'Commands/CommandController', + 'Shared/Actioneer', 'Shared/FormatHelpers' - ], function (App, Marionette, ButtonsView, ManualSearchLayout, ReleaseCollection, SeriesCollection, LoadingView, Messenger, CommandController, FormatHelpers) { + ], function (App, Marionette, ButtonsView, ManualSearchLayout, ReleaseCollection, SeriesCollection, LoadingView, Messenger, Actioneer, FormatHelpers) { return Marionette.Layout.extend({ template: 'Episode/Search/LayoutTemplate', @@ -39,16 +39,19 @@ define( e.preventDefault(); } - CommandController.Execute('episodeSearch', { episodeId: this.model.get('id') }); - var series = SeriesCollection.get(this.model.get('seriesId')); var seriesTitle = series.get('title'); var season = this.model.get('seasonNumber'); var episode = this.model.get('episodeNumber'); var message = seriesTitle + ' - ' + season + 'x' + FormatHelpers.pad(episode, 2); - Messenger.show({ - message: 'Search started for: ' + message + Actioneer.ExecuteCommand({ + command : 'episodeSearch', + properties : { + episodeId: this.model.get('id') + }, + errorMessage: 'Search failed for: ' + message, + startMessage: 'Search started for: ' + message }); App.vent.trigger(App.Commands.CloseModalCommand); diff --git a/UI/Router.js b/UI/Router.js index 984bf94ec..86b42c1ee 100644 --- a/UI/Router.js +++ b/UI/Router.js @@ -5,10 +5,11 @@ require( 'marionette', 'Controller', 'Series/SeriesCollection', + 'Shared/Actioneer', 'Navbar/NavbarView', 'jQuery/RouteBinder', 'jquery' - ], function (App, Marionette, Controller, SeriesCollection, NavbarView, RouterBinder, $) { + ], function (App, Marionette, Controller, SeriesCollection, Actioneer, NavbarView, RouterBinder, $) { var Router = Marionette.AppRouter.extend({ diff --git a/UI/SeasonPass/SeriesLayout.js b/UI/SeasonPass/SeriesLayout.js index 5de36f404..fd4d6b985 100644 --- a/UI/SeasonPass/SeriesLayout.js +++ b/UI/SeasonPass/SeriesLayout.js @@ -113,6 +113,8 @@ define( }, _setMonitored: function (seasonNumber) { + //TODO: use Actioneer? + var self = this; var promise = $.ajax({ diff --git a/UI/Series/Details/SeasonLayout.js b/UI/Series/Details/SeasonLayout.js index 1244050e8..facc530f1 100644 --- a/UI/Series/Details/SeasonLayout.js +++ b/UI/Series/Details/SeasonLayout.js @@ -7,9 +7,8 @@ define( 'Cells/EpisodeTitleCell', 'Cells/RelativeDateCell', 'Cells/EpisodeStatusCell', - 'Commands/CommandController', 'Shared/Actioneer' - ], function ( Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, CommandController, Actioneer) { + ], function ( Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, Actioneer) { return Marionette.Layout.extend({ template: 'Series/Details/SeasonLayoutTemplate', @@ -101,9 +100,10 @@ define( seriesId : this.model.get('seriesId'), seasonNumber: this.model.get('seasonNumber') }, - element : this.ui.seasonSearch, - failMessage : 'Search for season {0} failed'.format(this.model.get('seasonNumber')), - startMessage: 'Search for season {0} started'.format(this.model.get('seasonNumber')) + element : this.ui.seasonSearch, + errorMessage : 'Search for season {0} failed'.format(this.model.get('seasonNumber')), + startMessage : 'Search for season {0} started'.format(this.model.get('seasonNumber')), + successMessage: 'Search for season {0} completed'.format(this.model.get('seasonNumber')) }); }, @@ -143,13 +143,13 @@ define( _seasonRename: function () { Actioneer.ExecuteCommand({ - command : 'renameSeason', - properties : { + command : 'renameSeason', + properties : { seriesId : this.model.get('seriesId'), seasonNumber: this.model.get('seasonNumber') }, - element : this.ui.seasonRename, - failMessage: 'Season rename failed' + element : this.ui.seasonRename, + errorMessage: 'Season rename failed' }); } }); diff --git a/UI/Series/Details/SeasonMenu/ItemView.js b/UI/Series/Details/SeasonMenu/ItemView.js index 2ffe52418..1ab230734 100644 --- a/UI/Series/Details/SeasonMenu/ItemView.js +++ b/UI/Series/Details/SeasonMenu/ItemView.js @@ -51,7 +51,7 @@ define( seasonNumber: this.model.get('seasonNumber') }, element : this.ui.seasonSearch, - failMessage : 'Search for season {0} failed'.format(this.model.get('seasonNumber')), + errorMessage: 'Search for season {0} failed'.format(this.model.get('seasonNumber')), startMessage: 'Search for season {0} started'.format(this.model.get('seasonNumber')) }); }, diff --git a/UI/Series/Details/SeriesDetailsLayout.js b/UI/Series/Details/SeriesDetailsLayout.js index 8f073cc96..0d614e281 100644 --- a/UI/Series/Details/SeriesDetailsLayout.js +++ b/UI/Series/Details/SeriesDetailsLayout.js @@ -154,10 +154,10 @@ define( properties : { seriesId: this.model.get('id') }, - element : this.ui.rename, - context : this, - onSuccess : this._refetchEpisodeFiles, - failMessage: 'Series search failed' + element : this.ui.rename, + context : this, + onSuccess : this._refetchEpisodeFiles, + errorMessage: 'Series search failed' }); }, @@ -168,7 +168,7 @@ define( seriesId: this.model.get('id') }, element : this.ui.search, - failMessage : 'Series search failed', + errorMessage: 'Series search failed', startMessage: 'Search for {0} started'.format(this.model.get('title')) }); }, diff --git a/UI/Series/Index/SeriesIndexLayout.js b/UI/Series/Index/SeriesIndexLayout.js index b35234589..59ae9163b 100644 --- a/UI/Series/Index/SeriesIndexLayout.js +++ b/UI/Series/Index/SeriesIndexLayout.js @@ -140,7 +140,6 @@ define( this._fetchCollection(); }, - initialize: function () { this.seriesCollection = SeriesCollection; @@ -148,7 +147,6 @@ define( this.listenTo(SeriesCollection, 'remove', this._renderView); }, - _renderView: function () { if (SeriesCollection.length === 0) { @@ -164,7 +162,6 @@ define( } }, - onShow: function () { this._showToolbar(); this._renderView(); diff --git a/UI/Settings/Notifications/EditTemplate.html b/UI/Settings/Notifications/EditTemplate.html index dba9e30f9..91e9ecdb7 100644 --- a/UI/Settings/Notifications/EditTemplate.html +++ b/UI/Settings/Notifications/EditTemplate.html @@ -66,7 +66,7 @@ {{/if}} - +
diff --git a/UI/Settings/Notifications/EditView.js b/UI/Settings/Notifications/EditView.js index 312e48b88..be47a7db6 100644 --- a/UI/Settings/Notifications/EditView.js +++ b/UI/Settings/Notifications/EditView.js @@ -6,11 +6,11 @@ define([ 'Settings/Notifications/Model', 'Settings/Notifications/DeleteView', 'Shared/Messenger', - 'Commands/CommandController', + 'Shared/Actioneer', 'Mixins/AsModelBoundView', 'Form/FormBuilder' -], function (App, Marionette, NotificationModel, DeleteView, Messenger, CommandController, AsModelBoundView) { +], function (App, Marionette, NotificationModel, DeleteView, Messenger, Actioneer, AsModelBoundView) { var model = Marionette.ItemView.extend({ template: 'Settings/Notifications/EditTemplate', @@ -70,41 +70,28 @@ define([ var testCommand = this.model.get('testCommand'); if (testCommand) { this.idle = false; - this.ui.testButton.addClass('disabled'); - this.ui.testIcon.addClass('icon-spinner icon-spin'); - var properties = {}; _.each(this.model.get('fields'), function (field) { properties[field.name] = field.value; }); - var self = this; - var commandPromise = CommandController.Execute(testCommand, properties); - commandPromise.done(function () { - Messenger.show({ - message: 'Notification settings tested successfully' - }); + Actioneer.ExecuteCommand({ + command : testCommand, + properties : properties, + button : this.ui.testButton, + element : this.ui.testIcon, + errorMessage : 'Failed to test notification settings', + successMessage: 'Notification settings tested successfully', + always : this._testOnAlways, + context : this }); + } + }, - commandPromise.fail(function (options) { - if (options.readyState === 0 || options.status === 0) { - return; - } - - Messenger.show({ - message: 'Failed to test notification settings', - type : 'error' - }); - }); - - commandPromise.always(function () { - if (!self.isClosed) { - self.ui.testButton.removeClass('disabled'); - self.ui.testIcon.removeClass('icon-spinner icon-spin'); - self.idle = true; - } - }); + _testOnAlways: function () { + if (!this.isClosed) { + this.idle = true; } } }); diff --git a/UI/Shared/Actioneer.js b/UI/Shared/Actioneer.js index 929147ff1..ac59a7ff8 100644 --- a/UI/Shared/Actioneer.js +++ b/UI/Shared/Actioneer.js @@ -1,15 +1,30 @@ 'use strict'; -define(['Commands/CommandController', 'Shared/Messenger'], - function(CommandController, Messenger) { - return { +define( + [ + 'Commands/CommandController', + 'Commands/CommandCollection', + 'Shared/Messenger'], + function(CommandController, CommandCollection, Messenger) { + + var actioneer = Marionette.AppRouter.extend({ + + initialize: function () { + this.trackedCommands = []; + CommandCollection.fetch(); + this.listenTo(CommandCollection, 'sync', this._handleCommands); + }, + ExecuteCommand: function (options) { options.iconClass = this._getIconClass(options.element); - this._showStartMessage(options); + if (options.button) { + options.button.addClass('disable'); + } + this._setSpinnerOnElement(options); var promise = CommandController.Execute(options.command, options.properties); - this._handlePromise(promise, options); + this._showStartMessage(options, promise); }, SaveModel: function (options) { @@ -24,15 +39,7 @@ define(['Commands/CommandController', 'Shared/Messenger'], _handlePromise: function (promise, options) { promise.done(function () { - if (options.successMessage) { - Messenger.show({ - message: options.successMessage - }); - } - - if (options.onSuccess) { - options.onSuccess.call(options.context); - } + self._onSuccess(options); }); promise.fail(function (ajaxOptions) { @@ -40,31 +47,41 @@ define(['Commands/CommandController', 'Shared/Messenger'], return; } - if (options.failMessage) { - Messenger.show({ - message: options.failMessage, - type : 'error' - }); - } - - if (options.onError) { - options.onError.call(options.context); - } + self._onError(options); }); promise.always(function () { + self._onComplete(options); + }); + }, - if (options.leaveIcon) { - options.element.removeClass('icon-spin'); + _handleCommands: function () { + var self = this; + + _.each(this.trackedCommands, function (trackedCommand){ + if (trackedCommand.completed === true) { + return; } - else { - options.element.addClass(options.iconClass); - options.element.removeClass('icon-nd-spinner'); + var options = trackedCommand.options; + var command = CommandCollection.find({ 'id': trackedCommand.id }); + + if (!command) { + return; } - if (options.always) { - options.always.call(options.context); + if (command.get('state') === 'completed') { + trackedCommand.completed = true; + + self._onSuccess(options, command.get('id')); + self._onComplete(options); + } + + if (command.get('state') === 'failed') { + trackedCommand.completed = true; + + self._onError(options, command.get('id')); + self._onComplete(options); } }); }, @@ -74,6 +91,10 @@ define(['Commands/CommandController', 'Shared/Messenger'], }, _setSpinnerOnElement: function (options) { + if (!options.element) { + return; + } + if (options.leaveIcon) { options.element.addClass('icon-spin'); } @@ -84,12 +105,79 @@ define(['Commands/CommandController', 'Shared/Messenger'], } }, - _showStartMessage: function (options) { - if (options.startMessage) { + _onSuccess: function (options, id) { + if (options.successMessage) { Messenger.show({ - message: options.startMessage + id : id, + message: options.successMessage, + type : 'success' }); } + + if (options.onSuccess) { + options.onSuccess.call(options.context); + } + }, + + _onError: function (options, id) { + if (options.errorMessage) { + Messenger.show({ + id : id, + message: options.errorMessage, + type : 'error' + }); + } + + if (options.onError) { + options.onError.call(options.context); + } + }, + + _onComplete: function (options) { + if (options.button) { + options.button.removeClass('disable'); + } + + if (options.leaveIcon) { + options.element.removeClass('icon-spin'); + } + + else { + options.element.addClass(options.iconClass); + options.element.removeClass('icon-nd-spinner'); + options.element.removeClass('icon-spin'); + } + + if (options.always) { + options.always.call(options.context); + } + }, + + _showStartMessage: function (options, promise) { + var self = this; + + if (!promise) { + if (options.startMessage) { + Messenger.show({ + message: options.startMessage + }); + } + + return; + } + + promise.done(function (data) { + self.trackedCommands.push({ id: data.id, options: options }); + + if (options.startMessage) { + Messenger.show({ + id : data.id, + message: options.startMessage + }); + } + }); } - } + }); + + return new actioneer(); }); diff --git a/UI/Shared/Messenger.js b/UI/Shared/Messenger.js index 8f04009d9..1188e0fe5 100644 --- a/UI/Shared/Messenger.js +++ b/UI/Shared/Messenger.js @@ -13,6 +13,10 @@ define(function () { options.hideAfter = 5; break; + case 'success': + options.hideAfter = 5; + break; + default : options.hideAfter = 0; } @@ -22,11 +26,11 @@ define(function () { message : options.message, type : options.type, showCloseButton: true, - hideAfter : options.hideAfter + hideAfter : options.hideAfter, + id : options.id }); }, - monitor: function (options) { if (!options.promise) { diff --git a/UI/Shared/Toolbar/Button/ButtonView.js b/UI/Shared/Toolbar/Button/ButtonView.js index 32e8b3fbc..04814ccd3 100644 --- a/UI/Shared/Toolbar/Button/ButtonView.js +++ b/UI/Shared/Toolbar/Button/ButtonView.js @@ -3,9 +3,9 @@ define( [ 'app', 'marionette', - 'Commands/CommandController', + 'Shared/Actioneer', 'Shared/Messenger' - ], function (App, Marionette, CommandController, Messenger) { + ], function (App, Marionette, Actioneer, Messenger) { return Marionette.ItemView.extend({ template : 'Shared/Toolbar/ButtonTemplate', @@ -19,7 +19,6 @@ define( icon: '.x-icon' }, - initialize: function () { this.storageKey = this.model.get('menuKey') + ':' + this.model.get('key'); this.idle = true; @@ -45,68 +44,19 @@ define( }, invokeCommand: function () { - //TODO: Use Actioneer to handle icon swapping - var command = this.model.get('command'); if (command) { this.idle = false; - this.$el.addClass('disabled'); - this.ui.icon.addClass('icon-spinner icon-spin'); - var self = this; - var commandPromise = CommandController.Execute(command); - commandPromise.done(function () { - if (self.model.get('successMessage')) { - Messenger.show({ - message: self.model.get('successMessage') - }); - } - - if (self.model.get('onSuccess')) { - if (!self.model.ownerContext) { - throw 'ownerContext must be set.'; - } - - self.model.get('onSuccess').call(self.model.ownerContext); - } + Actioneer.ExecuteCommand({ + command : command, + button : this.$el, + element : this.ui.icon, + errorMessage : this.model.get('errorMessage'), + successMessage: this.model.get('successMessage'), + always : this._commandAlways, + context : this }); - - commandPromise.fail(function (options) { - if (options.readyState === 0 || options.status === 0) { - return; - } - - if (self.model.get('errorMessage')) { - Messenger.show({ - message: self.model.get('errorMessage'), - type : 'error' - }); - } - - if (self.model.get('onError')) { - if (!self.model.ownerContext) { - throw 'ownerContext must be set.'; - } - - self.model.get('onError').call(self.model.ownerContext); - } - }); - - commandPromise.always(function () { - if (!self.isClosed) { - self.$el.removeClass('disabled'); - self.ui.icon.removeClass('icon-spinner icon-spin'); - self.idle = true; - } - }); - - if (self.model.get('always')) { - if (!self.model.ownerContext) { - throw 'ownerContext must be set.'; - } - - self.model.get('always').call(self.model.ownerContext); - } } }, @@ -133,8 +83,13 @@ define( if (callback) { callback.call(this.model.ownerContext); } - } + }, + _commandAlways: function () { + if (!this.isClosed) { + this.idle = true; + } + } }); }); diff --git a/UI/Shared/Toolbar/ToolbarLayout.js b/UI/Shared/Toolbar/ToolbarLayout.js index 701fdf07d..8945337a2 100644 --- a/UI/Shared/Toolbar/ToolbarLayout.js +++ b/UI/Shared/Toolbar/ToolbarLayout.js @@ -30,10 +30,8 @@ define( this.left = options.left; this.right = options.right; this.toolbarContext = options.context; - }, - onShow: function () { if (this.left) { _.each(this.left, this._showToolbarLeft, this); @@ -51,7 +49,6 @@ define( this._showToolbar(element, index, 'right'); }, - _showToolbar: function (buttonGroup, index, position) { var groupCollection = new ButtonCollection(); From 1e7db2287e3729c3edd39101bf8f3aa29b1e5c04 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 30 Aug 2013 20:39:05 -0700 Subject: [PATCH 010/131] ScheduledTasks properly set last run time now --- NzbDrone.Api/Commands/CommandConnection.cs | 6 +++--- NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs | 6 +++--- NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs | 6 +++--- NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs | 6 +++--- NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs | 6 +++--- NzbDrone.Core/Jobs/TaskManager.cs | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/NzbDrone.Api/Commands/CommandConnection.cs b/NzbDrone.Api/Commands/CommandConnection.cs index a09125734..1d9285d0b 100644 --- a/NzbDrone.Api/Commands/CommandConnection.cs +++ b/NzbDrone.Api/Commands/CommandConnection.cs @@ -20,17 +20,17 @@ public override string Resource public void HandleAsync(CommandStartedEvent message) { - BroadcastMessage(message.Command); + BroadcastMessage(message.TrackedCommand); } public void HandleAsync(CommandCompletedEvent message) { - BroadcastMessage(message.Command); + BroadcastMessage(message.TrackedCommand); } public void Handle(CommandFailedEvent message) { - BroadcastMessage(message.Command); + BroadcastMessage(message.TrackedCommand); } private void BroadcastMessage(TrackedCommand trackedCommand) diff --git a/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs index 2c1f4f312..f4831361e 100644 --- a/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandCompletedEvent.cs @@ -4,11 +4,11 @@ namespace NzbDrone.Common.Messaging.Events { public class CommandCompletedEvent : IEvent { - public TrackedCommand Command { get; private set; } + public TrackedCommand TrackedCommand { get; private set; } - public CommandCompletedEvent(TrackedCommand command) + public CommandCompletedEvent(TrackedCommand trackedCommand) { - Command = command; + TrackedCommand = trackedCommand; } } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs index 8ed4b5f75..b93a5597c 100644 --- a/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandExecutedEvent.cs @@ -4,11 +4,11 @@ namespace NzbDrone.Common.Messaging.Events { public class CommandExecutedEvent : IEvent { - public TrackedCommand Command { get; private set; } + public TrackedCommand TrackedCommand { get; private set; } - public CommandExecutedEvent(TrackedCommand command) + public CommandExecutedEvent(TrackedCommand trackedCommand) { - Command = command; + TrackedCommand = trackedCommand; } } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs index f796f0f03..5749ca00a 100644 --- a/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandFailedEvent.cs @@ -5,12 +5,12 @@ namespace NzbDrone.Common.Messaging.Events { public class CommandFailedEvent : IEvent { - public TrackedCommand Command { get; private set; } + public TrackedCommand TrackedCommand { get; private set; } public Exception Exception { get; private set; } - public CommandFailedEvent(TrackedCommand command, Exception exception) + public CommandFailedEvent(TrackedCommand trackedCommand, Exception exception) { - Command = command; + TrackedCommand = trackedCommand; Exception = exception; } } diff --git a/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs b/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs index 14296c02a..9247fbd45 100644 --- a/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs +++ b/NzbDrone.Common/Messaging/Events/CommandStartedEvent.cs @@ -4,11 +4,11 @@ namespace NzbDrone.Common.Messaging.Events { public class CommandStartedEvent : IEvent { - public TrackedCommand Command { get; private set; } + public TrackedCommand TrackedCommand { get; private set; } - public CommandStartedEvent(TrackedCommand command) + public CommandStartedEvent(TrackedCommand trackedCommand) { - Command = command; + TrackedCommand = trackedCommand; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Jobs/TaskManager.cs b/NzbDrone.Core/Jobs/TaskManager.cs index 2f5314d1f..4dcfdd56c 100644 --- a/NzbDrone.Core/Jobs/TaskManager.cs +++ b/NzbDrone.Core/Jobs/TaskManager.cs @@ -79,7 +79,7 @@ public void Handle(ApplicationStartedEvent message) public void HandleAsync(CommandExecutedEvent message) { - var scheduledTask = _scheduledTaskRepository.All().SingleOrDefault(c => c.TypeName == message.Command.GetType().FullName); + var scheduledTask = _scheduledTaskRepository.All().SingleOrDefault(c => c.TypeName == message.TrackedCommand.Command.GetType().FullName); if (scheduledTask != null) { From 0894fc0e777b1f49481a39d7e19f614599605199 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 30 Aug 2013 23:19:19 -0700 Subject: [PATCH 011/131] Fixing CommandIntegrationTest - for now --- .../Messaging/Tracking/TrackedCommand.cs | 6 +++- .../CommandIntegerationTests.cs | 29 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs index cb00dd8c7..37f69de88 100644 --- a/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs +++ b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs @@ -12,7 +12,11 @@ public class TrackedCommand public DateTime StateChangeTime { get; set; } public TimeSpan Runtime { get; set; } public Exception Exception { get; set; } - + + public TrackedCommand() + { + } + public TrackedCommand(ICommand command, CommandState state) { Id = command.CommandId; diff --git a/NzbDrone.Integration.Test/CommandIntegerationTests.cs b/NzbDrone.Integration.Test/CommandIntegerationTests.cs index c1e06bac1..af3342c2b 100644 --- a/NzbDrone.Integration.Test/CommandIntegerationTests.cs +++ b/NzbDrone.Integration.Test/CommandIntegerationTests.cs @@ -1,5 +1,10 @@ -using NUnit.Framework; +using System.Net; +using FluentAssertions; +using NUnit.Framework; using NzbDrone.Api.Commands; +using NzbDrone.Common.Messaging.Tracking; +using NzbDrone.Common.Serializer; +using RestSharp; namespace NzbDrone.Integration.Test { @@ -9,7 +14,27 @@ public class CommandIntegrationTest : IntegrationTest [Test] public void should_be_able_to_run_rss_sync() { - Commands.Post(new CommandResource {Command = "rsssync"}); + var request = new RestRequest("command") + { + RequestFormat = DataFormat.Json, + Method = Method.POST + }; + + request.AddBody(new CommandResource {Command = "rsssync"}); + + var restClient = new RestClient("http://localhost:8989/api"); + var response = restClient.Execute(request); + + if (response.ErrorException != null) + { + throw response.ErrorException; + } + + response.ErrorMessage.Should().BeBlank(); + response.StatusCode.Should().Be(HttpStatusCode.Created); + + var trackedCommand = Json.Deserialize(response.Content); + trackedCommand.Id.Should().NotBeNullOrEmpty(); } } } \ No newline at end of file From e68fe9033d535edd82a4ba08d59e43d4f96fe0c9 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 31 Aug 2013 09:12:37 -0700 Subject: [PATCH 012/131] If nzbdrone restarts mid command the client will treat it as failed --- UI/Shared/Actioneer.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UI/Shared/Actioneer.js b/UI/Shared/Actioneer.js index ac59a7ff8..516a0e7b7 100644 --- a/UI/Shared/Actioneer.js +++ b/UI/Shared/Actioneer.js @@ -67,6 +67,10 @@ define( var command = CommandCollection.find({ 'id': trackedCommand.id }); if (!command) { + trackedCommand.completed = true; + + self._onError(options, trackedCommand.id); + self._onComplete(options); return; } @@ -75,6 +79,7 @@ define( self._onSuccess(options, command.get('id')); self._onComplete(options); + return; } if (command.get('state') === 'failed') { From eeda4e83f9de2eef76ea97560dbc921e54c290af Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 31 Aug 2013 21:23:21 -0700 Subject: [PATCH 013/131] Fixed the broken tests --- .../MessageAggregatorCommandTests.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs index a0534a1ba..35d7d03d1 100644 --- a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs +++ b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs @@ -3,6 +3,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Common.Messaging; +using NzbDrone.Common.Messaging.Tracking; using NzbDrone.Test.Common; namespace NzbDrone.Common.Test.EventingTests @@ -27,6 +28,13 @@ public void Setup() .Setup(c => c.Build(typeof(IExecute))) .Returns(_executorB.Object); + Mocker.GetMock() + .Setup(c => c.TrackIfNew(It.IsAny())) + .Returns(new TrackedCommand(new CommandA(), CommandState.Running)); + + Mocker.GetMock() + .Setup(c => c.TrackIfNew(It.IsAny())) + .Returns(new TrackedCommand(new CommandB(), CommandState.Running)); } [Test] @@ -34,6 +42,10 @@ public void should_publish_command_to_executor() { var commandA = new CommandA(); + Mocker.GetMock() + .Setup(c => c.TrackIfNew(commandA)) + .Returns(new TrackedCommand(commandA, CommandState.Running)); + Subject.PublishCommand(commandA); _executorA.Verify(c => c.Execute(commandA), Times.Once()); @@ -55,6 +67,9 @@ public void should_not_publish_to_incompatible_executor() { var commandA = new CommandA(); + Mocker.GetMock() + .Setup(c => c.TrackIfNew(commandA)) + .Returns(new TrackedCommand(commandA, CommandState.Running)); Subject.PublishCommand(commandA); From c928ccb20167c0846b66fe27ccc5292fae81ccc9 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 1 Sep 2013 19:55:45 -0700 Subject: [PATCH 014/131] Added progress messaging, using info logging Also extension methods for complete and failed (for coloured UI messaging) --- NzbDrone.Api/Commands/CommandConnection.cs | 4 +- NzbDrone.Api/NzbDrone.Api.csproj | 3 ++ .../ProgressMessageConnection.cs | 24 +++++++++++ .../ProgressMessageModule.cs | 21 ++++++++++ .../ProgressMessageResource.cs | 12 ++++++ .../MessageAggregatorCommandTests.cs | 8 ++-- .../Instrumentation/LogEventExtensions.cs | 1 - .../Instrumentation/LoggerExtensions.cs | 40 +++++++++++++++++++ NzbDrone.Common/Messaging/IProcessMessage.cs | 1 - .../Tracking/CommandTrackingService.cs | 12 +++--- .../Messaging/Tracking/ProcessState.cs | 14 +++++++ .../Messaging/Tracking/TrackedCommand.cs | 11 +---- NzbDrone.Common/NzbDrone.Common.csproj | 2 + NzbDrone.Core/Indexers/RssSyncService.cs | 3 +- NzbDrone.Core/NzbDrone.Core.csproj | 2 +- .../ProgressMessaging/ProgressMessage.cs | 5 +-- ...gingTarget.cs => ProgressMessageTarget.cs} | 8 +++- .../ProgressMessageCollection.js | 40 +++++++++++++++++++ UI/ProgressMessaging/ProgressMessageModel.js | 8 ++++ UI/Router.js | 3 +- UI/Series/Index/SeriesIndexLayout.js | 1 - 21 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 NzbDrone.Api/ProgressMessaging/ProgressMessageConnection.cs create mode 100644 NzbDrone.Api/ProgressMessaging/ProgressMessageModule.cs create mode 100644 NzbDrone.Api/ProgressMessaging/ProgressMessageResource.cs create mode 100644 NzbDrone.Common/Instrumentation/LoggerExtensions.cs create mode 100644 NzbDrone.Common/Messaging/Tracking/ProcessState.cs rename NzbDrone.Core/ProgressMessaging/{ProgressMessagingTarget.cs => ProgressMessageTarget.cs} (85%) create mode 100644 UI/ProgressMessaging/ProgressMessageCollection.js create mode 100644 UI/ProgressMessaging/ProgressMessageModel.js diff --git a/NzbDrone.Api/Commands/CommandConnection.cs b/NzbDrone.Api/Commands/CommandConnection.cs index 1d9285d0b..227c69bec 100644 --- a/NzbDrone.Api/Commands/CommandConnection.cs +++ b/NzbDrone.Api/Commands/CommandConnection.cs @@ -11,7 +11,7 @@ namespace NzbDrone.Api.Commands public class CommandConnection : NzbDronePersistentConnection, IHandleAsync, IHandleAsync, - IHandle + IHandleAsync { public override string Resource { @@ -28,7 +28,7 @@ public void HandleAsync(CommandCompletedEvent message) BroadcastMessage(message.TrackedCommand); } - public void Handle(CommandFailedEvent message) + public void HandleAsync(CommandFailedEvent message) { BroadcastMessage(message.TrackedCommand); } diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj index fe4ffcc5a..0be2d8ce9 100644 --- a/NzbDrone.Api/NzbDrone.Api.csproj +++ b/NzbDrone.Api/NzbDrone.Api.csproj @@ -86,6 +86,9 @@ + + + diff --git a/NzbDrone.Api/ProgressMessaging/ProgressMessageConnection.cs b/NzbDrone.Api/ProgressMessaging/ProgressMessageConnection.cs new file mode 100644 index 000000000..a5b4afdb0 --- /dev/null +++ b/NzbDrone.Api/ProgressMessaging/ProgressMessageConnection.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.AspNet.SignalR; +using Microsoft.AspNet.SignalR.Infrastructure; +using NzbDrone.Api.SignalR; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.ProgressMessaging; + +namespace NzbDrone.Api.ProgressMessaging +{ + public class ProgressMessageConnection : NzbDronePersistentConnection, + IHandleAsync + { + public override string Resource + { + get { return "/ProgressMessage"; } + } + + public void HandleAsync(NewProgressMessageEvent message) + { + var context = ((ConnectionManager)GlobalHost.ConnectionManager).GetConnection(GetType()); + context.Connection.Broadcast(message.ProgressMessage); + } + } +} diff --git a/NzbDrone.Api/ProgressMessaging/ProgressMessageModule.cs b/NzbDrone.Api/ProgressMessaging/ProgressMessageModule.cs new file mode 100644 index 000000000..a06db9c24 --- /dev/null +++ b/NzbDrone.Api/ProgressMessaging/ProgressMessageModule.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Nancy; +using NzbDrone.Api.Extensions; + +namespace NzbDrone.Api.ProgressMessaging +{ + public class ProgressMessageModule : NzbDroneRestModule + { + public ProgressMessageModule() + { + Get["/"] = x => GetAllMessages(); + } + + private Response GetAllMessages() + { + return new List().AsResponse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Api/ProgressMessaging/ProgressMessageResource.cs b/NzbDrone.Api/ProgressMessaging/ProgressMessageResource.cs new file mode 100644 index 000000000..3117eb142 --- /dev/null +++ b/NzbDrone.Api/ProgressMessaging/ProgressMessageResource.cs @@ -0,0 +1,12 @@ +using System; +using NzbDrone.Api.REST; + +namespace NzbDrone.Api.ProgressMessaging +{ + public class ProgressMessageResource : RestResource + { + public DateTime Time { get; set; } + public String CommandId { get; set; } + public String Message { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs index 35d7d03d1..b5c45bef0 100644 --- a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs +++ b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs @@ -30,11 +30,11 @@ public void Setup() Mocker.GetMock() .Setup(c => c.TrackIfNew(It.IsAny())) - .Returns(new TrackedCommand(new CommandA(), CommandState.Running)); + .Returns(new TrackedCommand(new CommandA(), ProcessState.Running)); Mocker.GetMock() .Setup(c => c.TrackIfNew(It.IsAny())) - .Returns(new TrackedCommand(new CommandB(), CommandState.Running)); + .Returns(new TrackedCommand(new CommandB(), ProcessState.Running)); } [Test] @@ -44,7 +44,7 @@ public void should_publish_command_to_executor() Mocker.GetMock() .Setup(c => c.TrackIfNew(commandA)) - .Returns(new TrackedCommand(commandA, CommandState.Running)); + .Returns(new TrackedCommand(commandA, ProcessState.Running)); Subject.PublishCommand(commandA); @@ -69,7 +69,7 @@ public void should_not_publish_to_incompatible_executor() Mocker.GetMock() .Setup(c => c.TrackIfNew(commandA)) - .Returns(new TrackedCommand(commandA, CommandState.Running)); + .Returns(new TrackedCommand(commandA, ProcessState.Running)); Subject.PublishCommand(commandA); diff --git a/NzbDrone.Common/Instrumentation/LogEventExtensions.cs b/NzbDrone.Common/Instrumentation/LogEventExtensions.cs index cb2fe44f2..373aa9201 100644 --- a/NzbDrone.Common/Instrumentation/LogEventExtensions.cs +++ b/NzbDrone.Common/Instrumentation/LogEventExtensions.cs @@ -13,7 +13,6 @@ public static string GetHash(this LogEventInfo logEvent) return HashUtil.CalculateCrc(hashSeed); } - public static string GetFormattedMessage(this LogEventInfo logEvent) { var message = logEvent.FormattedMessage; diff --git a/NzbDrone.Common/Instrumentation/LoggerExtensions.cs b/NzbDrone.Common/Instrumentation/LoggerExtensions.cs new file mode 100644 index 000000000..9816965c7 --- /dev/null +++ b/NzbDrone.Common/Instrumentation/LoggerExtensions.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog; +using NzbDrone.Common.Messaging.Tracking; + +namespace NzbDrone.Common.Instrumentation +{ + public static class LoggerExtensions + { + public static void Complete(this Logger logger, string message) + { + var logEvent = new LogEventInfo(LogLevel.Info, logger.Name, message); + logEvent.Properties.Add("Status", ProcessState.Completed); + + logger.Log(logEvent); + } + + public static void Complete(this Logger logger, string message, params object[] args) + { + var formattedMessage = String.Format(message, args); + Complete(logger, formattedMessage); + } + + public static void Failed(this Logger logger, string message) + { + var logEvent = new LogEventInfo(LogLevel.Info, logger.Name, message); + logEvent.Properties.Add("Status", ProcessState.Failed); + + logger.Log(logEvent); + } + + public static void Failed(this Logger logger, string message, params object[] args) + { + var formattedMessage = String.Format(message, args); + Failed(logger, formattedMessage); + } + } +} diff --git a/NzbDrone.Common/Messaging/IProcessMessage.cs b/NzbDrone.Common/Messaging/IProcessMessage.cs index b008d9e9b..d22eeea64 100644 --- a/NzbDrone.Common/Messaging/IProcessMessage.cs +++ b/NzbDrone.Common/Messaging/IProcessMessage.cs @@ -4,7 +4,6 @@ public interface IProcessMessage { } public interface IProcessMessageAsync : IProcessMessage { } - public interface IProcessMessage : IProcessMessage { } public interface IProcessMessageAsync : IProcessMessageAsync { } diff --git a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs index 2cb3b65ab..27c0c8bf1 100644 --- a/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs +++ b/NzbDrone.Common/Messaging/Tracking/CommandTrackingService.cs @@ -33,7 +33,7 @@ public TrackedCommand TrackIfNew(ICommand command) return null; } - var trackedCommand = new TrackedCommand(command, CommandState.Running); + var trackedCommand = new TrackedCommand(command, ProcessState.Running); Store(trackedCommand); return trackedCommand; @@ -45,7 +45,7 @@ public ExistingCommand TrackNewOrGet(ICommand command) if (trackedCommand == null) { - trackedCommand = new TrackedCommand(command, CommandState.Running); + trackedCommand = new TrackedCommand(command, ProcessState.Running); Store(trackedCommand); return new ExistingCommand(false, trackedCommand); @@ -57,7 +57,7 @@ public ExistingCommand TrackNewOrGet(ICommand command) public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime) { trackedCommand.StateChangeTime = DateTime.UtcNow; - trackedCommand.State = CommandState.Completed; + trackedCommand.State = ProcessState.Completed; trackedCommand.Runtime = runtime; Store(trackedCommand); @@ -68,7 +68,7 @@ public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime) public TrackedCommand Failed(TrackedCommand trackedCommand, Exception e) { trackedCommand.StateChangeTime = DateTime.UtcNow; - trackedCommand.State = CommandState.Failed; + trackedCommand.State = ProcessState.Failed; trackedCommand.Exception = e; Store(trackedCommand); @@ -94,7 +94,7 @@ public TrackedCommand FindExisting(ICommand command) private List Running(Type type = null) { - var running = AllTracked().Where(i => i.State == CommandState.Running); + var running = AllTracked().Where(i => i.State == ProcessState.Running); if (type != null) { @@ -116,7 +116,7 @@ private void Store(TrackedCommand trackedCommand) public void Execute(TrackedCommandCleanupCommand message) { - var old = AllTracked().Where(c => c.State != CommandState.Running && c.StateChangeTime < DateTime.UtcNow.AddMinutes(-5)); + var old = AllTracked().Where(c => c.State != ProcessState.Running && c.StateChangeTime < DateTime.UtcNow.AddMinutes(-5)); foreach (var trackedCommand in old) { diff --git a/NzbDrone.Common/Messaging/Tracking/ProcessState.cs b/NzbDrone.Common/Messaging/Tracking/ProcessState.cs new file mode 100644 index 000000000..dc79c37f4 --- /dev/null +++ b/NzbDrone.Common/Messaging/Tracking/ProcessState.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Common.Messaging.Tracking +{ + public enum ProcessState + { + Running, + Completed, + Failed + } +} diff --git a/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs index 37f69de88..35b0e05ac 100644 --- a/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs +++ b/NzbDrone.Common/Messaging/Tracking/TrackedCommand.cs @@ -8,7 +8,7 @@ public class TrackedCommand public String Name { get; private set; } public String Type { get; private set; } public ICommand Command { get; private set; } - public CommandState State { get; set; } + public ProcessState State { get; set; } public DateTime StateChangeTime { get; set; } public TimeSpan Runtime { get; set; } public Exception Exception { get; set; } @@ -17,7 +17,7 @@ public TrackedCommand() { } - public TrackedCommand(ICommand command, CommandState state) + public TrackedCommand(ICommand command, ProcessState state) { Id = command.CommandId; Name = command.GetType().Name; @@ -27,11 +27,4 @@ public TrackedCommand(ICommand command, CommandState state) StateChangeTime = DateTime.UtcNow; } } - - public enum CommandState - { - Running = 0, - Completed = 1, - Failed = 2 - } } diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index 75b255d08..d25e5eb61 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -92,6 +92,8 @@ + + diff --git a/NzbDrone.Core/Indexers/RssSyncService.cs b/NzbDrone.Core/Indexers/RssSyncService.cs index baf414fac..dcbf340b1 100644 --- a/NzbDrone.Core/Indexers/RssSyncService.cs +++ b/NzbDrone.Core/Indexers/RssSyncService.cs @@ -1,5 +1,6 @@ using System.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; @@ -38,7 +39,7 @@ public void Sync() var decisions = _downloadDecisionMaker.GetRssDecision(reports); var qualifiedReports = _downloadApprovedReports.DownloadApproved(decisions); - _logger.Info("RSS Sync Completed. Reports found: {0}, Reports downloaded: {1}", reports.Count, qualifiedReports.Count()); + _logger.Complete("RSS Sync Completed. Reports found: {0}, Reports downloaded: {1}", reports.Count, qualifiedReports.Count()); } public void Execute(RssSyncCommand message) diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 6a13f8b82..6cb78cca8 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -221,7 +221,7 @@ - + diff --git a/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs b/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs index 876087efb..b9bc8fc6d 100644 --- a/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs +++ b/NzbDrone.Core/ProgressMessaging/ProgressMessage.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using NzbDrone.Common.Messaging.Tracking; namespace NzbDrone.Core.ProgressMessaging { @@ -10,5 +8,6 @@ public class ProgressMessage public DateTime Time { get; set; } public String CommandId { get; set; } public String Message { get; set; } + public ProcessState Status { get; set; } } } diff --git a/NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs b/NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs similarity index 85% rename from NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs rename to NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs index 247fa7686..ee99f7599 100644 --- a/NzbDrone.Core/ProgressMessaging/ProgressMessagingTarget.cs +++ b/NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs @@ -4,17 +4,18 @@ using NLog.Layouts; using NLog.Targets; using NzbDrone.Common.Messaging; +using NzbDrone.Common.Messaging.Tracking; using NzbDrone.Core.Lifecycle; namespace NzbDrone.Core.ProgressMessaging { - public class ProgressMessagingTarget : TargetWithLayout, IHandle, IHandle + public class ProgressMessageTarget : TargetWithLayout, IHandle, IHandle { private readonly IMessageAggregator _messageAggregator; public LoggingRule Rule { get; set; } - public ProgressMessagingTarget(IMessageAggregator messageAggregator) + public ProgressMessageTarget(IMessageAggregator messageAggregator) { _messageAggregator = messageAggregator; } @@ -55,10 +56,13 @@ protected override void Write(LogEventInfo logEvent) return; } + var status = logEvent.Properties.ContainsKey("Status") ? (ProcessState)logEvent.Properties["Status"] : ProcessState.Running; + var message = new ProgressMessage(); message.Time = logEvent.TimeStamp; message.CommandId = commandId; message.Message = logEvent.FormattedMessage; + message.Status = status; _messageAggregator.PublishEvent(new NewProgressMessageEvent(message)); } diff --git a/UI/ProgressMessaging/ProgressMessageCollection.js b/UI/ProgressMessaging/ProgressMessageCollection.js new file mode 100644 index 000000000..063307f10 --- /dev/null +++ b/UI/ProgressMessaging/ProgressMessageCollection.js @@ -0,0 +1,40 @@ +'use strict'; +define( + [ + 'backbone', + 'ProgressMessaging/ProgressMessageModel', + 'Shared/Messenger', + 'Mixins/backbone.signalr.mixin' + ], function (Backbone, ProgressMessageModel, Messenger) { + + var ProgressMessageCollection = Backbone.Collection.extend({ + url : window.ApiRoot + '/progressmessage', + model: ProgressMessageModel + }); + + var collection = new ProgressMessageCollection().bindSignalR(); + + collection.signalRconnection.received(function (message) { + + var type = getMessengerType(message.status); + + Messenger.show({ + id : message.commandId, + message: message.message, + type : type + }); + }); + + var getMessengerType = function (status) { + switch (status) { + case 'completed': + return 'success'; + case 'failed': + return 'error'; + default: + return 'info'; + } + } + + return collection; + }); diff --git a/UI/ProgressMessaging/ProgressMessageModel.js b/UI/ProgressMessaging/ProgressMessageModel.js new file mode 100644 index 000000000..33a6217c8 --- /dev/null +++ b/UI/ProgressMessaging/ProgressMessageModel.js @@ -0,0 +1,8 @@ +'use strict'; +define( + [ + 'backbone' + ], function (Backbone) { + return Backbone.Model.extend({ + }); + }); diff --git a/UI/Router.js b/UI/Router.js index 86b42c1ee..4388c4f69 100644 --- a/UI/Router.js +++ b/UI/Router.js @@ -5,11 +5,12 @@ require( 'marionette', 'Controller', 'Series/SeriesCollection', + 'ProgressMessaging/ProgressMessageCollection', 'Shared/Actioneer', 'Navbar/NavbarView', 'jQuery/RouteBinder', 'jquery' - ], function (App, Marionette, Controller, SeriesCollection, Actioneer, NavbarView, RouterBinder, $) { + ], function (App, Marionette, Controller, SeriesCollection, ProgressMessageCollection, Actioneer, NavbarView, RouterBinder, $) { var Router = Marionette.AppRouter.extend({ diff --git a/UI/Series/Index/SeriesIndexLayout.js b/UI/Series/Index/SeriesIndexLayout.js index 59ae9163b..dd44e3cb6 100644 --- a/UI/Series/Index/SeriesIndexLayout.js +++ b/UI/Series/Index/SeriesIndexLayout.js @@ -105,7 +105,6 @@ define( title : 'RSS Sync', icon : 'icon-rss', command : 'rsssync', - successMessage: 'RSS Sync Completed', errorMessage : 'RSS Sync Failed!' }, { From e0735de9dab525f4dc7408c1cb1f36b5e59dda77 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 1 Sep 2013 20:46:43 -0700 Subject: [PATCH 015/131] semi-colon required --- UI/ProgressMessaging/ProgressMessageCollection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/ProgressMessaging/ProgressMessageCollection.js b/UI/ProgressMessaging/ProgressMessageCollection.js index 063307f10..eb7317b4d 100644 --- a/UI/ProgressMessaging/ProgressMessageCollection.js +++ b/UI/ProgressMessaging/ProgressMessageCollection.js @@ -34,7 +34,7 @@ define( default: return 'info'; } - } + }; return collection; }); From 95b21358c451ce9834596f00385e40dcdf5a7203 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 2 Sep 2013 22:02:47 -0700 Subject: [PATCH 016/131] Episode files are refreshed after season is renamed --- UI/Episode/Summary/Layout.js | 67 ------------------------ UI/Series/Details/SeasonLayout.js | 12 ++++- UI/Series/Details/SeriesDetailsLayout.js | 7 +++ UI/app.js | 3 +- 4 files changed, 19 insertions(+), 70 deletions(-) delete mode 100644 UI/Episode/Summary/Layout.js diff --git a/UI/Episode/Summary/Layout.js b/UI/Episode/Summary/Layout.js deleted file mode 100644 index b263c5682..000000000 --- a/UI/Episode/Summary/Layout.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; -define( - [ - 'app', - 'marionette', - 'backgrid', - 'Cells/FileSizeCell', - 'Cells/QualityCell', - 'Episode/Summary/NoFileView' - ], function (App, Marionette, Backgrid, FileSizeCell, QualityCell, NoFileView) { - - return Marionette.Layout.extend({ - template: 'Episode/Summary/LayoutTemplate', - - regions: { - overview: '.episode-overview', - activity: '.episode-file-info' - }, - - columns: - [ - { - name : 'path', - label : 'Path', - cell : 'string', - sortable: false - }, - { - name : 'size', - label : 'Size', - cell : FileSizeCell, - sortable: false - }, - { - name : 'quality', - label : 'Quality', - cell : QualityCell, - sortable: false, - editable: true - } - ], - - templateHelpers: {}, - - initialize: function (options) { - if (!this.model.series) { - this.templateHelpers.series = options.series.toJSON(); - } - }, - - onShow: function () { - if (this.model.get('hasFile')) { - var episodeFile = App.request(App.Reqres.GetEpisodeFileById, this.model.get('episodeFileId')); - - this.activity.show(new Backgrid.Grid({ - collection: new Backbone.Collection(episodeFile), - columns : this.columns, - className : 'table table-bordered'spinn - })); - } - - else { - this.activity.show(new NoFileView()); - } - } - }); - }); diff --git a/UI/Series/Details/SeasonLayout.js b/UI/Series/Details/SeasonLayout.js index 1244050e8..ea6b76ceb 100644 --- a/UI/Series/Details/SeasonLayout.js +++ b/UI/Series/Details/SeasonLayout.js @@ -1,6 +1,7 @@ 'use strict'; define( [ + 'app', 'marionette', 'backgrid', 'Cells/ToggleCell', @@ -9,7 +10,7 @@ define( 'Cells/EpisodeStatusCell', 'Commands/CommandController', 'Shared/Actioneer' - ], function ( Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, CommandController, Actioneer) { + ], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, CommandController, Actioneer) { return Marionette.Layout.extend({ template: 'Series/Details/SeasonLayoutTemplate', @@ -74,6 +75,7 @@ define( } this.episodeCollection = options.episodeCollection.bySeason(this.model.get('seasonNumber')); + this.series = options.series; this.listenTo(this.model, 'sync', function () { this._afterSeasonMonitored(); @@ -149,8 +151,14 @@ define( seasonNumber: this.model.get('seasonNumber') }, element : this.ui.seasonRename, - failMessage: 'Season rename failed' + failMessage: 'Season rename failed', + context : this, + onSuccess : this._afterRename }); + }, + + _afterRename: function () { + App.vent.trigger(App.Events.SeasonRenamed, { series: this.series, seasonNumber: this.model.get('seasonNumber') }); } }); }); diff --git a/UI/Series/Details/SeriesDetailsLayout.js b/UI/Series/Details/SeriesDetailsLayout.js index 8f073cc96..b241e18b3 100644 --- a/UI/Series/Details/SeriesDetailsLayout.js +++ b/UI/Series/Details/SeriesDetailsLayout.js @@ -60,6 +60,7 @@ define( }, this); this.listenTo(App.vent, App.Events.SeriesDeleted, this._onSeriesDeleted); + this.listenTo(App.vent, App.Events.SeasonRenamed, this._onSeasonRenamed); }, onShow: function () { @@ -213,6 +214,12 @@ define( _refetchEpisodeFiles: function () { this.episodeFileCollection.fetch(); + }, + + _onSeasonRenamed: function(event) { + if (this.model.get('id') === event.series.get('id')) { + this._refetchEpisodeFiles(); + } } }); }); diff --git a/UI/app.js b/UI/app.js index c3ba25d6f..c1e54221d 100644 --- a/UI/app.js +++ b/UI/app.js @@ -188,7 +188,8 @@ define( app.Events = { SeriesAdded : 'series:added', - SeriesDeleted: 'series:deleted' + SeriesDeleted: 'series:deleted', + SeasonRenamed: 'season:renamed' }; app.Commands = { From bceaee27a379bd81be43832b06180d8f84fa12a6 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 18:42:30 -0700 Subject: [PATCH 017/131] moved logging config to in-process --- NzbDrone.Api/NancyBootstrapper.cs | 3 +- .../SignalR/BasicResourceConnection.cs | 3 +- NzbDrone.Common/DiskProvider.cs | 3 +- .../EnvironmentInfo/AppFolderInfo.cs | 3 +- .../EnvironmentInfo/RuntimeInfo.cs | 1 - .../EnvironmentInfo/StartupArguments.cs | 12 -- .../ApplicationLogLayoutRenderer.cs | 26 ---- .../DirSeparatorLayoutRenderer.cs | 19 --- .../Instrumentation/ExceptronTarget.cs | 10 -- .../GlobalExceptionHandlers.cs | 5 +- NzbDrone.Common/Instrumentation/LogTargets.cs | 138 ++++++++++++++++++ .../Instrumentation/LogglyTarget.cs | 11 +- .../Instrumentation/NzbDroneLogger.cs | 42 ++++++ .../UpdateLogLayoutRenderer.cs | 28 ---- NzbDrone.Common/NzbDrone.Common.csproj | 5 +- NzbDrone.Common/ProcessProvider.cs | 3 +- .../Security/IgnoreCertErrorPolicy.cs | 3 +- NzbDrone.Common/ServiceProvider.cs | 3 +- NzbDrone.Common/TPL/TaskExtensions.cs | 3 +- NzbDrone.Console/ConsoleApp.cs | 9 +- .../DatabaseTargetFixture.cs | 4 +- .../Download/Clients/PneumaticClient.cs | 3 +- .../Sabnzbd/SabAutoConfigureService.cs | 3 +- NzbDrone.Core/Indexers/BasicRssParser.cs | 3 +- .../Indexers/NzbClub/NzbClubParser.cs | 3 +- NzbDrone.Core/Indexers/XElementExtensions.cs | 3 +- .../MediaFiles/RecycleBinProvider.cs | 3 +- .../Notifications/Growl/GrowlService.cs | 3 +- .../Notifications/Xbmc/XbmcService.cs | 3 +- NzbDrone.Core/Parser/Parser.cs | 3 +- .../Providers/XemCommunicationProvider.cs | 3 +- NzbDrone.Core/Providers/XemProvider.cs | 3 +- NzbDrone.Core/Rest/RestSharpExtensions.cs | 5 +- .../RootFolders/RootFolderService.cs | 3 +- NzbDrone.Core/Tv/EpisodeService.cs | 3 +- NzbDrone.Host/Bootstrap.cs | 2 +- NzbDrone.Host/NLog.config | 31 ---- NzbDrone.Host/NzbDrone.Host.csproj | 4 - NzbDrone.Host/Owin/NlogTextWriter.cs | 3 +- NzbDrone.Host/PlatformValidation.cs | 3 +- NzbDrone.Update/NLog.config | 17 --- NzbDrone.Update/NzbDrone.Update.csproj | 4 - NzbDrone.Update/UpdateApp.cs | 8 +- NzbDrone/WindowsApp.cs | 10 +- 44 files changed, 257 insertions(+), 203 deletions(-) delete mode 100644 NzbDrone.Common/Instrumentation/ApplicationLogLayoutRenderer.cs delete mode 100644 NzbDrone.Common/Instrumentation/DirSeparatorLayoutRenderer.cs create mode 100644 NzbDrone.Common/Instrumentation/LogTargets.cs create mode 100644 NzbDrone.Common/Instrumentation/NzbDroneLogger.cs delete mode 100644 NzbDrone.Common/Instrumentation/UpdateLogLayoutRenderer.cs delete mode 100644 NzbDrone.Host/NLog.config delete mode 100644 NzbDrone.Update/NLog.config diff --git a/NzbDrone.Api/NancyBootstrapper.cs b/NzbDrone.Api/NancyBootstrapper.cs index 5f65c80e2..4e481119a 100644 --- a/NzbDrone.Api/NancyBootstrapper.cs +++ b/NzbDrone.Api/NancyBootstrapper.cs @@ -6,6 +6,7 @@ using NzbDrone.Api.ErrorManagement; using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions.Pipelines; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Lifecycle; @@ -21,7 +22,7 @@ public class NancyBootstrapper : TinyIoCNancyBootstrapper public NancyBootstrapper(TinyIoCContainer tinyIoCContainer) { _tinyIoCContainer = tinyIoCContainer; - _logger = LogManager.GetCurrentClassLogger(); + _logger = NzbDroneLogger.GetLogger(); } protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) diff --git a/NzbDrone.Api/SignalR/BasicResourceConnection.cs b/NzbDrone.Api/SignalR/BasicResourceConnection.cs index e56ae4fd2..4166b07cb 100644 --- a/NzbDrone.Api/SignalR/BasicResourceConnection.cs +++ b/NzbDrone.Api/SignalR/BasicResourceConnection.cs @@ -2,6 +2,7 @@ using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Infrastructure; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore.Events; @@ -18,7 +19,7 @@ public abstract class BasicResourceConnection : public BasicResourceConnection() { - _logger = LogManager.GetCurrentClassLogger(); + _logger = NzbDroneLogger.GetLogger(this); } protected override Task OnConnected(IRequest request, string connectionId) diff --git a/NzbDrone.Common/DiskProvider.cs b/NzbDrone.Common/DiskProvider.cs index 851ba4550..592a7d12c 100644 --- a/NzbDrone.Common/DiskProvider.cs +++ b/NzbDrone.Common/DiskProvider.cs @@ -8,6 +8,7 @@ using NLog; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Common { @@ -58,7 +59,7 @@ static extern bool GetDiskFreeSpaceEx(string lpDirectoryName, out ulong lpTotalNumberOfBytes, out ulong lpTotalNumberOfFreeBytes); - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public HashSet SpecialFolders { diff --git a/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs b/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs index e93395756..04f7b29ab 100644 --- a/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs +++ b/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs @@ -4,6 +4,7 @@ using System.Security.AccessControl; using System.Security.Principal; using NLog; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Common.EnvironmentInfo { @@ -30,7 +31,7 @@ public AppFolderInfo(IDiskProvider diskProvider, IStartupArguments startupArgume DATA_SPECIAL_FOLDER = Environment.SpecialFolder.ApplicationData; } - _logger = LogManager.GetCurrentClassLogger(); + _logger = NzbDroneLogger.GetLogger(this); if (startupArguments.Args.ContainsKey(StartupArguments.APPDATA)) { diff --git a/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs b/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs index 7bd6e8d3c..f2d0e4caf 100644 --- a/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs +++ b/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.IO; using System.Security.Principal; -using System.ServiceProcess; using NLog; namespace NzbDrone.Common.EnvironmentInfo diff --git a/NzbDrone.Common/EnvironmentInfo/StartupArguments.cs b/NzbDrone.Common/EnvironmentInfo/StartupArguments.cs index 9075d64e0..5aeb9c351 100644 --- a/NzbDrone.Common/EnvironmentInfo/StartupArguments.cs +++ b/NzbDrone.Common/EnvironmentInfo/StartupArguments.cs @@ -17,14 +17,6 @@ public class StartupArguments : IStartupArguments public const string UNINSTALL_SERVICE = "u"; public const string HELP = "?"; - static StartupArguments() - { - if (RuntimeInfo.IsProduction) - { - Instance = new StartupArguments(""); - } - } - public StartupArguments(params string[] args) { Flags = new HashSet(); @@ -45,13 +37,9 @@ public StartupArguments(params string[] args) Flags.Add(flag); } } - - Instance = this; } public HashSet Flags { get; private set; } public Dictionary Args { get; private set; } - - public static IStartupArguments Instance { get; private set; } } } \ No newline at end of file diff --git a/NzbDrone.Common/Instrumentation/ApplicationLogLayoutRenderer.cs b/NzbDrone.Common/Instrumentation/ApplicationLogLayoutRenderer.cs deleted file mode 100644 index 2a2082d18..000000000 --- a/NzbDrone.Common/Instrumentation/ApplicationLogLayoutRenderer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.IO; -using System.Text; -using NLog; -using NLog.Config; -using NLog.LayoutRenderers; -using NzbDrone.Common.EnvironmentInfo; - -namespace NzbDrone.Common.Instrumentation -{ - [ThreadAgnostic] - [LayoutRenderer("appLog")] - public class ApplicationLogLayoutRenderer : LayoutRenderer - { - private readonly string _appData; - - public ApplicationLogLayoutRenderer() - { - _appData = Path.Combine(new AppFolderInfo(new DiskProvider(), StartupArguments.Instance ).GetLogFolder(), "nzbdrone.txt"); - } - - protected override void Append(StringBuilder builder, LogEventInfo logEvent) - { - builder.Append(_appData); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Common/Instrumentation/DirSeparatorLayoutRenderer.cs b/NzbDrone.Common/Instrumentation/DirSeparatorLayoutRenderer.cs deleted file mode 100644 index bb5658326..000000000 --- a/NzbDrone.Common/Instrumentation/DirSeparatorLayoutRenderer.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.IO; -using System.Text; -using NLog; -using NLog.Config; -using NLog.LayoutRenderers; - -namespace NzbDrone.Common.Instrumentation -{ - [ThreadAgnostic] - [LayoutRenderer("dirSeparator")] - public class DirSeparatorLayoutRenderer : LayoutRenderer - { - - protected override void Append(StringBuilder builder, LogEventInfo logEvent) - { - builder.Append(Path.DirectorySeparatorChar); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Common/Instrumentation/ExceptronTarget.cs b/NzbDrone.Common/Instrumentation/ExceptronTarget.cs index 59ff5e918..89208be7a 100644 --- a/NzbDrone.Common/Instrumentation/ExceptronTarget.cs +++ b/NzbDrone.Common/Instrumentation/ExceptronTarget.cs @@ -24,17 +24,7 @@ public class ExceptronTarget : Target public IExceptronClient ExceptronClient { get; internal set; } - private static ExceptronTarget _instance = new ExceptronTarget(); - public static void Register() - { - var rule = new LoggingRule("*", LogLevel.Warn, _instance); - - LogManager.Configuration.AddTarget("ExceptronTarget", _instance); - LogManager.Configuration.LoggingRules.Add(rule); - LogManager.ConfigurationReloaded += (sender, args) => Register(); - LogManager.ReconfigExistingLoggers(); - } protected override void InitializeTarget() { diff --git a/NzbDrone.Common/Instrumentation/GlobalExceptionHandlers.cs b/NzbDrone.Common/Instrumentation/GlobalExceptionHandlers.cs index 24fb64c61..20a076b58 100644 --- a/NzbDrone.Common/Instrumentation/GlobalExceptionHandlers.cs +++ b/NzbDrone.Common/Instrumentation/GlobalExceptionHandlers.cs @@ -6,12 +6,9 @@ namespace NzbDrone.Common.Instrumentation { public static class GlobalExceptionHandlers { - private static readonly Logger Logger = LogManager.GetLogger("Global"); - + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public static void Register() { - ExceptronTarget.Register(); - AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e.ExceptionObject as Exception)); TaskScheduler.UnobservedTaskException += ((s, e) => TaskException(e.Exception)); } diff --git a/NzbDrone.Common/Instrumentation/LogTargets.cs b/NzbDrone.Common/Instrumentation/LogTargets.cs new file mode 100644 index 000000000..1e0e3f419 --- /dev/null +++ b/NzbDrone.Common/Instrumentation/LogTargets.cs @@ -0,0 +1,138 @@ +using System; +using System.IO; +using NLog; +using NLog.Config; +using NLog.Targets; +using NzbDrone.Common.EnvironmentInfo; + +namespace NzbDrone.Common.Instrumentation +{ + public static class LogTargets + { + public static void Register(IStartupArguments startupArguments, bool updateApp, bool inConsole) + { + var appFolderInfo = new AppFolderInfo(new DiskProvider(), startupArguments); + + LogManager.Configuration = new LoggingConfiguration(); + + RegisterExceptron(); + + if (updateApp) + { + RegisterLoggly(); + RegisterUpdateFile(appFolderInfo); + } + else + { + if (inConsole && (OsInfo.IsLinux || new RuntimeInfo(null).IsUserInteractive)) + { + RegisterConsole(); + } + + RegisterAppFile(appFolderInfo); + } + } + + private static void RegisterConsole() + { + var level = LogLevel.Trace; + + if (RuntimeInfo.IsProduction) + { + level = LogLevel.Info; + } + + var coloredConsoleTarget = new ColoredConsoleTarget(); + + coloredConsoleTarget.Name = "consoleLogger"; + coloredConsoleTarget.Layout = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}${exception:format=ToString}${newline}}"; + + var loggingRule = new LoggingRule("*", level, coloredConsoleTarget); + + LogManager.Configuration.AddTarget("console", coloredConsoleTarget); + LogManager.Configuration.LoggingRules.Add(loggingRule); + + LogManager.ConfigurationReloaded += (sender, args) => RegisterConsole(); + LogManager.ReconfigExistingLoggers(); + } + + + const string FileLogLayout = @"${date:format=yy-M-d HH\:mm\:ss.f}|${level}|${logger}|${message}${onexception:inner=${newline}${newline}${exception:format=ToString}${newline}}"; + + private static void RegisterAppFile(IAppFolderInfo appFolderInfo) + { + var fileTarget = new FileTarget(); + + fileTarget.Name = "rollingFileLogger"; + fileTarget.FileName = Path.Combine(appFolderInfo.GetLogFolder(), "nzbdrone.txt"); + fileTarget.AutoFlush = true; + fileTarget.KeepFileOpen = false; + fileTarget.ConcurrentWrites = false; + fileTarget.ConcurrentWriteAttemptDelay = 50; + fileTarget.ConcurrentWriteAttempts = 10; + fileTarget.ArchiveAboveSize = 1024000; + fileTarget.MaxArchiveFiles = 5; + fileTarget.EnableFileDelete = true; + fileTarget.ArchiveNumbering = ArchiveNumberingMode.Rolling; + fileTarget.Layout = FileLogLayout; + + var loggingRule = new LoggingRule("*", LogLevel.Info, fileTarget); + + LogManager.Configuration.AddTarget("appfile", fileTarget); + LogManager.Configuration.LoggingRules.Add(loggingRule); + + LogManager.ConfigurationReloaded += (sender, args) => RegisterAppFile(appFolderInfo); + LogManager.ReconfigExistingLoggers(); + } + + + + private static void RegisterUpdateFile(IAppFolderInfo appFolderInfo) + { + var fileTarget = new FileTarget(); + + fileTarget.Name = "updateFileLogger"; + fileTarget.FileName = Path.Combine(appFolderInfo.GetUpdateLogFolder(), DateTime.Now.ToString("yy.MM.d-HH.mm") + ".txt"); + fileTarget.AutoFlush = true; + fileTarget.KeepFileOpen = false; + fileTarget.ConcurrentWrites = false; + fileTarget.ConcurrentWriteAttemptDelay = 50; + fileTarget.ConcurrentWriteAttempts = 100; + fileTarget.Layout = FileLogLayout; + + var loggingRule = new LoggingRule("*", LogLevel.Trace, fileTarget); + + LogManager.Configuration.AddTarget("updateFile", fileTarget); + LogManager.Configuration.LoggingRules.Add(loggingRule); + + LogManager.ConfigurationReloaded += (sender, args) => RegisterUpdateFile(appFolderInfo); + LogManager.ReconfigExistingLoggers(); + } + + private static void RegisterExceptron() + { + + var exceptronTarget = new ExceptronTarget(); + var rule = new LoggingRule("*", LogLevel.Warn, exceptronTarget); + + LogManager.Configuration.AddTarget("ExceptronTarget", exceptronTarget); + LogManager.Configuration.LoggingRules.Add(rule); + LogManager.ConfigurationReloaded += (sender, args) => RegisterExceptron(); + LogManager.ReconfigExistingLoggers(); + } + + + public static void RegisterLoggly() + { + var logglyTarger = new LogglyTarget(); + + var rule = new LoggingRule("*", LogLevel.Trace, logglyTarger); + + LogManager.Configuration.AddTarget("LogglyLogger", logglyTarger); + LogManager.Configuration.LoggingRules.Add(rule); + LogManager.ConfigurationReloaded += (sender, args) => RegisterLoggly(); + LogManager.ReconfigExistingLoggers(); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Common/Instrumentation/LogglyTarget.cs b/NzbDrone.Common/Instrumentation/LogglyTarget.cs index 33d953390..8f2817581 100644 --- a/NzbDrone.Common/Instrumentation/LogglyTarget.cs +++ b/NzbDrone.Common/Instrumentation/LogglyTarget.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using NLog; -using NLog.Config; using NLog.Layouts; using NLog.Targets; using NzbDrone.Common.EnvironmentInfo; @@ -13,16 +12,10 @@ public class LogglyTarget : TargetWithLayout { private Logger _logger; - public void Register(LogLevel minLevel) + public LogglyTarget() { Layout = new SimpleLayout("${callsite:className=false:fileName=false:includeSourcePath=false:methodName=true}"); - - var rule = new LoggingRule("*", minLevel, this); - - LogManager.Configuration.AddTarget("LogglyLogger", this); - LogManager.Configuration.LoggingRules.Add(rule); - LogManager.ConfigurationReloaded += (sender, args) => Register(minLevel); - LogManager.ReconfigExistingLoggers(); + } protected override void InitializeTarget() diff --git a/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs b/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs new file mode 100644 index 000000000..c722d5160 --- /dev/null +++ b/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs @@ -0,0 +1,42 @@ +using System; +using System.Diagnostics; +using NLog; + +namespace NzbDrone.Common.Instrumentation +{ + public static class NzbDroneLogger + { + public static Logger GetLogger() + { + string loggerName; + Type declaringType; + int framesToSkip = 1; + do + { + var frame = new StackFrame(framesToSkip, false); + var method = frame.GetMethod(); + declaringType = method.DeclaringType; + if (declaringType == null) + { + loggerName = method.Name; + break; + } + + framesToSkip++; + loggerName = declaringType.Name; + } while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase)); + + return LogManager.GetLogger(loggerName); + } + + public static Logger GetLogger(object obj) + { + return LogManager.GetLogger(obj.GetType().Name); + } + + public static Logger GetLogger() + { + return LogManager.GetLogger(typeof(T).Name); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Common/Instrumentation/UpdateLogLayoutRenderer.cs b/NzbDrone.Common/Instrumentation/UpdateLogLayoutRenderer.cs deleted file mode 100644 index 2f55d36de..000000000 --- a/NzbDrone.Common/Instrumentation/UpdateLogLayoutRenderer.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.IO; -using System.Text; -using NLog; -using NLog.Config; -using NLog.LayoutRenderers; -using NzbDrone.Common.EnvironmentInfo; - -namespace NzbDrone.Common.Instrumentation -{ - [ThreadAgnostic] - [LayoutRenderer("updateLog")] - public class UpdateLogLayoutRenderer : LayoutRenderer - { - private readonly string _appData; - - public UpdateLogLayoutRenderer() - { - _appData = Path.Combine(new AppFolderInfo(new DiskProvider(), StartupArguments.Instance).GetUpdateLogFolder(), DateTime.Now.ToString("yy.MM.d-HH.mm") + ".txt"); - - } - - protected override void Append(StringBuilder builder, LogEventInfo logEvent) - { - builder.Append(_appData); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index c1b17236f..d379a7a3a 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -92,6 +92,8 @@ + + @@ -99,11 +101,8 @@ - - - diff --git a/NzbDrone.Common/ProcessProvider.cs b/NzbDrone.Common/ProcessProvider.cs index 8df4198e8..ffb647709 100644 --- a/NzbDrone.Common/ProcessProvider.cs +++ b/NzbDrone.Common/ProcessProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using NLog; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Model; namespace NzbDrone.Common @@ -26,7 +27,7 @@ public interface IProcessProvider public class ProcessProvider : IProcessProvider { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public const string NZB_DRONE_PROCESS_NAME = "NzbDrone"; public const string NZB_DRONE_CONSOLE_PROCESS_NAME = "NzbDrone.Console"; diff --git a/NzbDrone.Common/Security/IgnoreCertErrorPolicy.cs b/NzbDrone.Common/Security/IgnoreCertErrorPolicy.cs index 1be964380..809b0fe74 100644 --- a/NzbDrone.Common/Security/IgnoreCertErrorPolicy.cs +++ b/NzbDrone.Common/Security/IgnoreCertErrorPolicy.cs @@ -3,12 +3,13 @@ using System.Security.Cryptography.X509Certificates; using NLog; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Common.Security { public static class IgnoreCertErrorPolicy { - private static readonly Logger Logger = LogManager.GetLogger("CertPolicy"); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public static void Register() { diff --git a/NzbDrone.Common/ServiceProvider.cs b/NzbDrone.Common/ServiceProvider.cs index 7287e36df..8c2206a63 100644 --- a/NzbDrone.Common/ServiceProvider.cs +++ b/NzbDrone.Common/ServiceProvider.cs @@ -5,6 +5,7 @@ using System.Linq; using System.ServiceProcess; using NLog; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Common { @@ -25,7 +26,7 @@ public class ServiceProvider : IServiceProvider { public const string NZBDRONE_SERVICE_NAME = "NzbDrone"; - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public virtual bool ServiceExist(string name) { diff --git a/NzbDrone.Common/TPL/TaskExtensions.cs b/NzbDrone.Common/TPL/TaskExtensions.cs index e655ac86f..855ae225c 100644 --- a/NzbDrone.Common/TPL/TaskExtensions.cs +++ b/NzbDrone.Common/TPL/TaskExtensions.cs @@ -1,11 +1,12 @@ using System.Threading.Tasks; using NLog; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Common.TPL { public static class TaskExtensions { - private static readonly Logger Logger = LogManager.GetLogger("TaskExtensions"); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public static Task LogExceptions(this Task task) { diff --git a/NzbDrone.Console/ConsoleApp.cs b/NzbDrone.Console/ConsoleApp.cs index 3119cc811..8b633510d 100644 --- a/NzbDrone.Console/ConsoleApp.cs +++ b/NzbDrone.Console/ConsoleApp.cs @@ -2,17 +2,22 @@ using System.Threading; using NLog; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; using NzbDrone.Host; namespace NzbDrone.Console { public static class ConsoleApp { + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); + public static void Main(string[] args) { try { - Bootstrap.Start(new StartupArguments(args), new ConsoleAlerts()); + var startupArgs = new StartupArguments(args); + LogTargets.Register(startupArgs, false, true); + Bootstrap.Start(startupArgs, new ConsoleAlerts()); } catch (TerminateApplicationException) { @@ -28,4 +33,4 @@ public static void Main(string[] args) } } } -} \ No newline at end of file +} diff --git a/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs b/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs index 6bb9644a9..22784f95b 100644 --- a/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs +++ b/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs @@ -3,6 +3,7 @@ using FluentAssertions; using NLog; using NUnit.Framework; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Datastore; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Instrumentation; @@ -36,8 +37,7 @@ public void Setup() LogManager.ReconfigExistingLoggers(); - _logger = LogManager.GetCurrentClassLogger(); - _loggerName = _logger.Name.Replace("NzbDrone.",""); + _logger = NzbDroneLogger.GetLogger(); _uniqueMessage = "Unique message: " + Guid.NewGuid().ToString(); } diff --git a/NzbDrone.Core/Download/Clients/PneumaticClient.cs b/NzbDrone.Core/Download/Clients/PneumaticClient.cs index a7e59b6a4..ff4929805 100644 --- a/NzbDrone.Core/Download/Clients/PneumaticClient.cs +++ b/NzbDrone.Core/Download/Clients/PneumaticClient.cs @@ -3,6 +3,7 @@ using System.IO; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Configuration; using NzbDrone.Core.Organizer; using NzbDrone.Core.Parser.Model; @@ -15,7 +16,7 @@ public class PneumaticClient : IDownloadClient private readonly IHttpProvider _httpProvider; private readonly IDiskProvider _diskProvider; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = NzbDroneLogger.GetLogger(); public PneumaticClient(IConfigService configService, IHttpProvider httpProvider, IDiskProvider diskProvider) diff --git a/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs b/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs index 6ff5a666a..224cae5c5 100644 --- a/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs +++ b/NzbDrone.Core/Download/Clients/Sabnzbd/SabAutoConfigureService.cs @@ -6,12 +6,13 @@ using System.Net.NetworkInformation; using System.Text.RegularExpressions; using NLog; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Core.Download.Clients.Sabnzbd { public class SabAutoConfigureService { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public SabModel AutoConfigureSab() { diff --git a/NzbDrone.Core/Indexers/BasicRssParser.cs b/NzbDrone.Core/Indexers/BasicRssParser.cs index 84c61f296..447a27674 100644 --- a/NzbDrone.Core/Indexers/BasicRssParser.cs +++ b/NzbDrone.Core/Indexers/BasicRssParser.cs @@ -7,6 +7,7 @@ using System.Xml; using System.Xml.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Indexers @@ -22,7 +23,7 @@ public class BasicRssParser : IParseFeed public BasicRssParser() { - _logger = LogManager.GetCurrentClassLogger(); + _logger = NzbDroneLogger.GetLogger(this); } public IEnumerable Process(string xml, string url) diff --git a/NzbDrone.Core/Indexers/NzbClub/NzbClubParser.cs b/NzbDrone.Core/Indexers/NzbClub/NzbClubParser.cs index 9c17b0ffa..30a3b899e 100644 --- a/NzbDrone.Core/Indexers/NzbClub/NzbClubParser.cs +++ b/NzbDrone.Core/Indexers/NzbClub/NzbClubParser.cs @@ -3,6 +3,7 @@ using System.Text.RegularExpressions; using System.Xml.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Indexers.NzbClub @@ -15,7 +16,7 @@ public class NzbClubParser : BasicRssParser public NzbClubParser() { - logger = LogManager.GetCurrentClassLogger(); + logger = NzbDroneLogger.GetLogger(); } diff --git a/NzbDrone.Core/Indexers/XElementExtensions.cs b/NzbDrone.Core/Indexers/XElementExtensions.cs index 8460c34d6..1608d0ec6 100644 --- a/NzbDrone.Core/Indexers/XElementExtensions.cs +++ b/NzbDrone.Core/Indexers/XElementExtensions.cs @@ -5,13 +5,14 @@ using System.Text.RegularExpressions; using System.Xml.Linq; using NLog; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Core.Indexers { public static class XElementExtensions { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); private static readonly Regex RemoveTimeZoneRegex = new Regex(@"\s[A-Z]{2,4}$", RegexOptions.Compiled); diff --git a/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs b/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs index ff3866b39..17f286c71 100644 --- a/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs +++ b/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs @@ -3,6 +3,7 @@ using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.Commands; @@ -23,7 +24,7 @@ public class RecycleBinProvider : IHandleAsync, IExecute { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); private readonly Application _growlApplication = new Application("NzbDrone"); private GrowlConnector _growlConnector; diff --git a/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs b/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs index cc0f9bf3c..6df04e75b 100644 --- a/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs +++ b/NzbDrone.Core/Notifications/Xbmc/XbmcService.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json.Linq; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Tv; using NzbDrone.Core.Model.Xbmc; @@ -21,7 +22,7 @@ public interface IXbmcService public class XbmcService : IXbmcService, IExecute { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); private readonly IHttpProvider _httpProvider; private readonly IEnumerable _apiProviders; diff --git a/NzbDrone.Core/Parser/Parser.cs b/NzbDrone.Core/Parser/Parser.cs index 3178b5084..4863e6b3a 100644 --- a/NzbDrone.Core/Parser/Parser.cs +++ b/NzbDrone.Core/Parser/Parser.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; @@ -13,7 +14,7 @@ namespace NzbDrone.Core.Parser { public static class Parser { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); private static readonly Regex[] ReportTitleRegex = new[] { diff --git a/NzbDrone.Core/Providers/XemCommunicationProvider.cs b/NzbDrone.Core/Providers/XemCommunicationProvider.cs index 803b74e65..5c0e07132 100644 --- a/NzbDrone.Core/Providers/XemCommunicationProvider.cs +++ b/NzbDrone.Core/Providers/XemCommunicationProvider.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NzbDrone.Common; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Model.Xem; namespace NzbDrone.Core.Providers @@ -20,7 +21,7 @@ public class XemCommunicationProvider : IXemCommunicationProvider { private readonly IHttpProvider _httpProvider; - private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger _logger = NzbDroneLogger.GetLogger(); private const string XEM_BASE_URL = "http://thexem.de/map/"; diff --git a/NzbDrone.Core/Providers/XemProvider.cs b/NzbDrone.Core/Providers/XemProvider.cs index 931793dfb..d2abb6776 100644 --- a/NzbDrone.Core/Providers/XemProvider.cs +++ b/NzbDrone.Core/Providers/XemProvider.cs @@ -3,6 +3,7 @@ using System.Linq; using NLog; using NzbDrone.Common.Cache; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Tv; @@ -25,7 +26,7 @@ public class XemProvider : IXemProvider, IExecute, IHa private readonly ISeriesService _seriesService; private readonly ICached _cache; - private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger _logger = NzbDroneLogger.GetLogger(); public XemProvider(IEpisodeService episodeService, IXemCommunicationProvider xemCommunicationProvider, diff --git a/NzbDrone.Core/Rest/RestSharpExtensions.cs b/NzbDrone.Core/Rest/RestSharpExtensions.cs index b0c09368c..33b5e681b 100644 --- a/NzbDrone.Core/Rest/RestSharpExtensions.cs +++ b/NzbDrone.Core/Rest/RestSharpExtensions.cs @@ -1,6 +1,7 @@ using System.Net; using NLog; using NzbDrone.Common.EnsureThat; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Serializer; using RestSharp; @@ -8,7 +9,7 @@ namespace NzbDrone.Core.Rest { public static class RestSharpExtensions { - private static readonly Logger Logger = LogManager.GetLogger("RestExtensions"); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public static IRestResponse ValidateResponse(this IRestResponse response, IRestClient restClient) { @@ -22,7 +23,7 @@ public static IRestResponse ValidateResponse(this IRestResponse response, IRestC Ensure.That(() => response.Request).IsNotNull(); Ensure.That(() => restClient).IsNotNull(); - Logger.Trace("Validating Responses from [{0}] [{1}] status: [{2}] body:[{3}]", response.Request.Method, restClient.BuildUri(response.Request), response.StatusCode, response.Content); + Logger.Trace("Validating Responses from [{0}] [{1}] status: [{2}]", response.Request.Method, restClient.BuildUri(response.Request), response.StatusCode); if (response.ResponseUri == null) { diff --git a/NzbDrone.Core/RootFolders/RootFolderService.cs b/NzbDrone.Core/RootFolders/RootFolderService.cs index 160cd3c9f..7360f898c 100644 --- a/NzbDrone.Core/RootFolders/RootFolderService.cs +++ b/NzbDrone.Core/RootFolders/RootFolderService.cs @@ -4,6 +4,7 @@ using System.IO; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Configuration; using NzbDrone.Core.Datastore; using NzbDrone.Core.Tv; @@ -23,7 +24,7 @@ public interface IRootFolderService public class RootFolderService : IRootFolderService { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); private readonly IBasicRepository _rootFolderRepository; private readonly IDiskProvider _diskProvider; private readonly ISeriesRepository _seriesRepository; diff --git a/NzbDrone.Core/Tv/EpisodeService.cs b/NzbDrone.Core/Tv/EpisodeService.cs index dce584fa4..7747510d8 100644 --- a/NzbDrone.Core/Tv/EpisodeService.cs +++ b/NzbDrone.Core/Tv/EpisodeService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Configuration; using NzbDrone.Core.Datastore; @@ -40,7 +41,7 @@ public class EpisodeService : IEpisodeService, IHandleAsync { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = NzbDroneLogger.GetLogger(); private readonly IEpisodeRepository _episodeRepository; private readonly IConfigService _configService; diff --git a/NzbDrone.Host/Bootstrap.cs b/NzbDrone.Host/Bootstrap.cs index e4b592fd1..7f108f799 100644 --- a/NzbDrone.Host/Bootstrap.cs +++ b/NzbDrone.Host/Bootstrap.cs @@ -12,7 +12,7 @@ public static class Bootstrap { public static IContainer Start(StartupArguments args, IUserAlert userAlert) { - var logger = LogManager.GetLogger("AppMain"); + var logger = NzbDroneLogger.GetLogger(); GlobalExceptionHandlers.Register(); IgnoreCertErrorPolicy.Register(); diff --git a/NzbDrone.Host/NLog.config b/NzbDrone.Host/NLog.config deleted file mode 100644 index 65103a066..000000000 --- a/NzbDrone.Host/NLog.config +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - Exception - ${exception:format=ToString} - - - - - - - - - - \ No newline at end of file diff --git a/NzbDrone.Host/NzbDrone.Host.csproj b/NzbDrone.Host/NzbDrone.Host.csproj index c625626ea..49c4850bd 100644 --- a/NzbDrone.Host/NzbDrone.Host.csproj +++ b/NzbDrone.Host/NzbDrone.Host.csproj @@ -141,10 +141,6 @@ - - Always - Designer - Designer diff --git a/NzbDrone.Host/Owin/NlogTextWriter.cs b/NzbDrone.Host/Owin/NlogTextWriter.cs index d4cd4da7d..fb912893f 100644 --- a/NzbDrone.Host/Owin/NlogTextWriter.cs +++ b/NzbDrone.Host/Owin/NlogTextWriter.cs @@ -1,12 +1,13 @@ using System.IO; using System.Text; using NLog; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Host.Owin { public class NlogTextWriter : TextWriter { - private readonly Logger logger = LogManager.GetCurrentClassLogger(); + private readonly Logger logger = NzbDroneLogger.GetLogger(); public override Encoding Encoding diff --git a/NzbDrone.Host/PlatformValidation.cs b/NzbDrone.Host/PlatformValidation.cs index 978a579ae..703918aca 100644 --- a/NzbDrone.Host/PlatformValidation.cs +++ b/NzbDrone.Host/PlatformValidation.cs @@ -3,12 +3,13 @@ using System.Reflection; using NLog; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; namespace NzbDrone.Host { public static class PlatformValidation { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public static bool IsValidate(IUserAlert userAlert) { diff --git a/NzbDrone.Update/NLog.config b/NzbDrone.Update/NLog.config deleted file mode 100644 index 8398980c9..000000000 --- a/NzbDrone.Update/NLog.config +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NzbDrone.Update/NzbDrone.Update.csproj b/NzbDrone.Update/NzbDrone.Update.csproj index c2d12c5c4..a1d42c2e0 100644 --- a/NzbDrone.Update/NzbDrone.Update.csproj +++ b/NzbDrone.Update/NzbDrone.Update.csproj @@ -63,10 +63,6 @@ - - Always - Designer - Designer diff --git a/NzbDrone.Update/UpdateApp.cs b/NzbDrone.Update/UpdateApp.cs index 167499373..3a882cd74 100644 --- a/NzbDrone.Update/UpdateApp.cs +++ b/NzbDrone.Update/UpdateApp.cs @@ -16,7 +16,7 @@ public class UpdateApp private readonly IProcessProvider _processProvider; private static IContainer _container; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = NzbDroneLogger.GetLogger(); public UpdateApp(IInstallUpdateService installUpdateService, IProcessProvider processProvider) { @@ -28,14 +28,16 @@ public static void Main(string[] args) { try { + var startupArgument = new StartupArguments(args); + LogTargets.Register(startupArgument, true, true); + Console.WriteLine("Starting NzbDrone Update Client"); IgnoreCertErrorPolicy.Register(); GlobalExceptionHandlers.Register(); - new LogglyTarget().Register(LogLevel.Trace); - _container = UpdateContainerBuilder.Build(new StartupArguments(args)); + _container = UpdateContainerBuilder.Build(startupArgument); logger.Info("Updating NzbDrone to version {0}", BuildInfo.Version); _container.Resolve().Start(args); diff --git a/NzbDrone/WindowsApp.cs b/NzbDrone/WindowsApp.cs index 4d4dc9d69..dd96cf596 100644 --- a/NzbDrone/WindowsApp.cs +++ b/NzbDrone/WindowsApp.cs @@ -2,6 +2,7 @@ using System.Windows.Forms; using NLog; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Instrumentation; using NzbDrone.Host; using NzbDrone.SysTray; @@ -9,12 +10,17 @@ namespace NzbDrone { public static class WindowsApp { + private static readonly Logger Logger = NzbDroneLogger.GetLogger(); public static void Main(string[] args) { try { - var container = Bootstrap.Start(new StartupArguments(args), new MessageBoxUserAlert()); + var startupArgs = new StartupArguments(args); + + LogTargets.Register(startupArgs, false, true); + + var container = Bootstrap.Start(startupArgs, new MessageBoxUserAlert()); container.Register(); container.Resolve().Start(); } @@ -28,4 +34,4 @@ public static void Main(string[] args) } } } -} \ No newline at end of file +} From b6e4f5ed460c8c0b8e0ec4d6036619550933e804 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 18:56:12 -0700 Subject: [PATCH 018/131] delete target folder before update --- NzbDrone.Update/UpdateEngine/InstallUpdateService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs b/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs index ffafff691..13626a3c7 100644 --- a/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs +++ b/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs @@ -64,6 +64,7 @@ public void Start(string installationFolder) try { + _diskProvider.DeleteFolder(installationFolder, true); _diskProvider.CopyFolder(_appFolderInfo.GetUpdatePackageFolder(), installationFolder); } catch (Exception e) From 2f204e3d29152c7ff62020f3308b3310ed8c26c3 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 19:13:13 -0700 Subject: [PATCH 019/131] fixed broken tests. --- .../InstrumentationTests/DatabaseTargetFixture.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs b/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs index 22784f95b..2b88348aa 100644 --- a/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs +++ b/NzbDrone.Core.Test/InstrumentationTests/DatabaseTargetFixture.cs @@ -15,8 +15,6 @@ namespace NzbDrone.Core.Test.InstrumentationTests [TestFixture] public class DatabaseTargetFixture : DbTest { - string _loggerName; - private static string _uniqueMessage; Logger _logger; @@ -37,7 +35,7 @@ public void Setup() LogManager.ReconfigExistingLoggers(); - _logger = NzbDroneLogger.GetLogger(); + _logger = NzbDroneLogger.GetLogger(); _uniqueMessage = "Unique message: " + Guid.NewGuid().ToString(); } @@ -119,7 +117,7 @@ public void Teardown() private void VerifyLog(Log logItem, LogLevel level) { logItem.Time.Should().BeWithin(TimeSpan.FromSeconds(2)); - logItem.Logger.Should().Be(_loggerName); + logItem.Logger.Should().Be(this.GetType().Name); logItem.Level.Should().Be(level.Name); logItem.Method.Should().Be(new StackTrace().GetFrame(1).GetMethod().Name); _logger.Name.Should().EndWith(logItem.Logger); From 7417f76086e9df5da4bca1f7303a204668c23710 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 19:32:30 -0700 Subject: [PATCH 020/131] updated logging/loggly --- NzbDrone.Common/Instrumentation/LogTargets.cs | 17 +++-------------- NzbDrone.Common/NzbDrone.Common.csproj | 2 +- NzbDrone.Common/packages.config | 2 +- .../Instrumentation/SetLoggingLevel.cs | 5 ++++- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/NzbDrone.Common/Instrumentation/LogTargets.cs b/NzbDrone.Common/Instrumentation/LogTargets.cs index 1e0e3f419..d63520e80 100644 --- a/NzbDrone.Common/Instrumentation/LogTargets.cs +++ b/NzbDrone.Common/Instrumentation/LogTargets.cs @@ -31,6 +31,8 @@ public static void Register(IStartupArguments startupArguments, bool updateApp, RegisterAppFile(appFolderInfo); } + + LogManager.ReconfigExistingLoggers(); } private static void RegisterConsole() @@ -51,9 +53,6 @@ private static void RegisterConsole() LogManager.Configuration.AddTarget("console", coloredConsoleTarget); LogManager.Configuration.LoggingRules.Add(loggingRule); - - LogManager.ConfigurationReloaded += (sender, args) => RegisterConsole(); - LogManager.ReconfigExistingLoggers(); } @@ -80,9 +79,6 @@ private static void RegisterAppFile(IAppFolderInfo appFolderInfo) LogManager.Configuration.AddTarget("appfile", fileTarget); LogManager.Configuration.LoggingRules.Add(loggingRule); - - LogManager.ConfigurationReloaded += (sender, args) => RegisterAppFile(appFolderInfo); - LogManager.ReconfigExistingLoggers(); } @@ -104,9 +100,6 @@ private static void RegisterUpdateFile(IAppFolderInfo appFolderInfo) LogManager.Configuration.AddTarget("updateFile", fileTarget); LogManager.Configuration.LoggingRules.Add(loggingRule); - - LogManager.ConfigurationReloaded += (sender, args) => RegisterUpdateFile(appFolderInfo); - LogManager.ReconfigExistingLoggers(); } private static void RegisterExceptron() @@ -117,12 +110,10 @@ private static void RegisterExceptron() LogManager.Configuration.AddTarget("ExceptronTarget", exceptronTarget); LogManager.Configuration.LoggingRules.Add(rule); - LogManager.ConfigurationReloaded += (sender, args) => RegisterExceptron(); - LogManager.ReconfigExistingLoggers(); } - public static void RegisterLoggly() + private static void RegisterLoggly() { var logglyTarger = new LogglyTarget(); @@ -130,8 +121,6 @@ public static void RegisterLoggly() LogManager.Configuration.AddTarget("LogglyLogger", logglyTarger); LogManager.Configuration.LoggingRules.Add(rule); - LogManager.ConfigurationReloaded += (sender, args) => RegisterLoggly(); - LogManager.ReconfigExistingLoggers(); } } diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index d379a7a3a..e392e51bb 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -41,7 +41,7 @@ False - ..\packages\loggly-csharp.2.2\lib\Loggly.dll + ..\packages\loggly-csharp.2.3\lib\net35\Loggly.dll diff --git a/NzbDrone.Common/packages.config b/NzbDrone.Common/packages.config index c1ce89767..7252d18f7 100644 --- a/NzbDrone.Common/packages.config +++ b/NzbDrone.Common/packages.config @@ -1,6 +1,6 @@  - + diff --git a/NzbDrone.Core/Instrumentation/SetLoggingLevel.cs b/NzbDrone.Core/Instrumentation/SetLoggingLevel.cs index 251ef6f38..1792a8b3c 100644 --- a/NzbDrone.Core/Instrumentation/SetLoggingLevel.cs +++ b/NzbDrone.Core/Instrumentation/SetLoggingLevel.cs @@ -2,6 +2,7 @@ using System.Linq; using NLog; using NLog.Config; +using NLog.Targets; using NzbDrone.Common.Messaging; using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration.Events; @@ -28,10 +29,12 @@ public void Reconfigure() var minimumLogLevel = LogLevel.FromString(_configFileProvider.LogLevel); var rules = LogManager.Configuration.LoggingRules; - var rollingFileLogger = rules.Single(s => s.Targets.Any(t => t.Name == "rollingFileLogger")); + var rollingFileLogger = rules.Single(s => s.Targets.Any(t => t is FileTarget)); rollingFileLogger.EnableLoggingForLevel(LogLevel.Trace); SetMinimumLogLevel(rollingFileLogger, minimumLogLevel); + + LogManager.ReconfigExistingLoggers(); } private void SetMinimumLogLevel(LoggingRule rule, LogLevel minimumLogLevel) From 5557ac84547bbaf6b6d9bec70063790e2775914c Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Mon, 2 Sep 2013 23:18:54 -0700 Subject: [PATCH 021/131] emergency hack to fix breaking trakt api. --- .../Trakt/{Show.cs => FullShow.cs} | 27 +++++++++++++++++++ NzbDrone.Core/MetadataSource/TraktProxy.cs | 26 ++++++++++++++++-- NzbDrone.Core/NzbDrone.Core.csproj | 2 +- 3 files changed, 52 insertions(+), 3 deletions(-) rename NzbDrone.Core/MetadataSource/Trakt/{Show.cs => FullShow.cs} (52%) diff --git a/NzbDrone.Core/MetadataSource/Trakt/Show.cs b/NzbDrone.Core/MetadataSource/Trakt/FullShow.cs similarity index 52% rename from NzbDrone.Core/MetadataSource/Trakt/Show.cs rename to NzbDrone.Core/MetadataSource/Trakt/FullShow.cs index bf7745d43..32c60c5fb 100644 --- a/NzbDrone.Core/MetadataSource/Trakt/Show.cs +++ b/NzbDrone.Core/MetadataSource/Trakt/FullShow.cs @@ -29,4 +29,31 @@ public class Show public List genres { get; set; } public List seasons { get; set; } } + + public class SearchShow + { + public string title { get; set; } + public int year { get; set; } + public string url { get; set; } + public int first_aired { get; set; } + public string first_aired_iso { get; set; } + public int first_aired_utc { get; set; } + public string country { get; set; } + public string overview { get; set; } + public int runtime { get; set; } + public string status { get; set; } + public string network { get; set; } + public string air_day { get; set; } + public string air_day_utc { get; set; } + public string air_time { get; set; } + public string air_time_utc { get; set; } + public string certification { get; set; } + public string imdb_id { get; set; } + public int tvdb_id { get; set; } + public int tvrage_id { get; set; } + public int last_updated { get; set; } + public string poster { get; set; } + public Images images { get; set; } + public List genres { get; set; } + } } \ No newline at end of file diff --git a/NzbDrone.Core/MetadataSource/TraktProxy.cs b/NzbDrone.Core/MetadataSource/TraktProxy.cs index 4a84c0cbd..2c18b5594 100644 --- a/NzbDrone.Core/MetadataSource/TraktProxy.cs +++ b/NzbDrone.Core/MetadataSource/TraktProxy.cs @@ -19,9 +19,9 @@ public List SearchForNewSeries(string title) { var client = BuildClient("search", "shows"); var restRequest = new RestRequest(GetSearchTerm(title)); - var response = client.ExecuteAndValidate>(restRequest); + var response = client.ExecuteAndValidate>(restRequest); - return response.Select(MapSeries).ToList(); + return response.Select(MapSearchSeries).ToList(); } @@ -77,6 +77,28 @@ private static Series MapSeries(Show show) return series; } + private static Series MapSearchSeries(SearchShow show) + { + var series = new Series(); + series.TvdbId = show.tvdb_id; + series.TvRageId = show.tvrage_id; + series.ImdbId = show.imdb_id; + series.Title = show.title; + series.CleanTitle = Parser.Parser.CleanSeriesTitle(show.title); + series.FirstAired = FromIso(show.first_aired_iso); + series.Overview = show.overview; + series.Runtime = show.runtime; + series.Network = show.network; + series.AirTime = show.air_time_utc; + series.TitleSlug = show.url.ToLower().Replace("http://trakt.tv/show/", ""); + series.Status = GetSeriesStatus(show.status); + + series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Banner, Url = show.images.banner }); + series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Poster, Url = GetPosterThumbnailUrl(show.images.poster) }); + series.Images.Add(new MediaCover.MediaCover { CoverType = MediaCoverTypes.Fanart, Url = show.images.fanart }); + return series; + } + private static Episode MapEpisode(Trakt.Episode traktEpisode) { var episode = new Episode(); diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 3f95a1ab6..793db0f0a 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -297,7 +297,7 @@ - + From c184ec2d983a3b307e052f9a3e1f15b5a4e51e93 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 3 Sep 2013 22:01:28 -0700 Subject: [PATCH 022/131] Progress messages are logged with Logger.Progress --- NzbDrone.Api/Indexers/ReleaseModule.cs | 14 ++-- .../Instrumentation/LoggerExtensions.cs | 29 ++++++--- .../DecisionEngine/DownloadDecisionMaker.cs | 21 ++++-- NzbDrone.Core/Download/DownloadService.cs | 3 +- .../SingleEpisodeSearchCriteria.cs | 2 +- .../IndexerSearch/EpisodeSearchService.cs | 15 ++++- .../IndexerSearch/NzbSearchService.cs | 8 ++- .../IndexerSearch/SeasonSearchService.cs | 14 +++- .../IndexerSearch/SeriesSearchService.cs | 13 +++- NzbDrone.Core/Indexers/IndexerFetchService.cs | 8 +-- NzbDrone.Core/Indexers/RssSyncService.cs | 6 +- NzbDrone.Core/MediaFiles/DiskScanService.cs | 4 ++ .../MediaFiles/RenameEpisodeFileService.cs | 9 +-- .../ProgressMessageTarget.cs | 7 +- NzbDrone.Core/Tv/EpisodeService.cs | 2 +- NzbDrone.Core/Tv/RefreshEpisodeService.cs | 2 +- NzbDrone.Core/Tv/RefreshSeriesService.cs | 64 ++++++++++--------- UI/Episode/Search/Layout.js | 7 +- .../ProgressMessageCollection.js | 8 ++- UI/Shared/Actioneer.js | 20 ++++-- 20 files changed, 166 insertions(+), 90 deletions(-) diff --git a/NzbDrone.Api/Indexers/ReleaseModule.cs b/NzbDrone.Api/Indexers/ReleaseModule.cs index aaf452261..28d104ffa 100644 --- a/NzbDrone.Api/Indexers/ReleaseModule.cs +++ b/NzbDrone.Api/Indexers/ReleaseModule.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using Nancy; +using NLog; using NzbDrone.Api.Mapping; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; using NzbDrone.Core.IndexerSearch; @@ -21,18 +23,21 @@ public class ReleaseModule : NzbDroneRestModule private readonly IMakeDownloadDecision _downloadDecisionMaker; private readonly IDownloadService _downloadService; private readonly IParsingService _parsingService; + private readonly Logger _logger; public ReleaseModule(IFetchAndParseRss rssFetcherAndParser, - ISearchForNzb nzbSearchService, - IMakeDownloadDecision downloadDecisionMaker, - IDownloadService downloadService, - IParsingService parsingService) + ISearchForNzb nzbSearchService, + IMakeDownloadDecision downloadDecisionMaker, + IDownloadService downloadService, + IParsingService parsingService, + Logger logger) { _rssFetcherAndParser = rssFetcherAndParser; _nzbSearchService = nzbSearchService; _downloadDecisionMaker = downloadDecisionMaker; _downloadService = downloadService; _parsingService = parsingService; + _logger = logger; GetResourceAll = GetReleases; Post["/"] = x=> DownloadRelease(this.Bind()); } @@ -60,6 +65,7 @@ private List GetReleases() private List GetEpisodeReleases(int episodeId) { var decisions = _nzbSearchService.EpisodeSearch(episodeId); + return MapDecisions(decisions); } diff --git a/NzbDrone.Common/Instrumentation/LoggerExtensions.cs b/NzbDrone.Common/Instrumentation/LoggerExtensions.cs index 9816965c7..305b3f610 100644 --- a/NzbDrone.Common/Instrumentation/LoggerExtensions.cs +++ b/NzbDrone.Common/Instrumentation/LoggerExtensions.cs @@ -9,12 +9,20 @@ namespace NzbDrone.Common.Instrumentation { public static class LoggerExtensions { + public static void Progress(this Logger logger, string message) + { + LogProgressMessage(logger, message, ProcessState.Running); + } + + public static void Progress(this Logger logger, string message, params object[] args) + { + var formattedMessage = String.Format(message, args); + Progress(logger, formattedMessage); + } + public static void Complete(this Logger logger, string message) { - var logEvent = new LogEventInfo(LogLevel.Info, logger.Name, message); - logEvent.Properties.Add("Status", ProcessState.Completed); - - logger.Log(logEvent); + LogProgressMessage(logger, message, ProcessState.Completed); } public static void Complete(this Logger logger, string message, params object[] args) @@ -25,10 +33,7 @@ public static void Complete(this Logger logger, string message, params object[] public static void Failed(this Logger logger, string message) { - var logEvent = new LogEventInfo(LogLevel.Info, logger.Name, message); - logEvent.Properties.Add("Status", ProcessState.Failed); - - logger.Log(logEvent); + LogProgressMessage(logger, message, ProcessState.Failed); } public static void Failed(this Logger logger, string message, params object[] args) @@ -36,5 +41,13 @@ public static void Failed(this Logger logger, string message, params object[] ar var formattedMessage = String.Format(message, args); Failed(logger, formattedMessage); } + + private static void LogProgressMessage(Logger logger, string message, ProcessState state) + { + var logEvent = new LogEventInfo(LogLevel.Info, logger.Name, message); + logEvent.Properties.Add("Status", state); + + logger.Log(logEvent); + } } } diff --git a/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs b/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs index d94036901..0dbc66f7d 100644 --- a/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs +++ b/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.DecisionEngine.Specifications.Search; using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.Parser; @@ -12,8 +13,8 @@ namespace NzbDrone.Core.DecisionEngine { public interface IMakeDownloadDecision { - List GetRssDecision(IEnumerable reports); - List GetSearchDecision(IEnumerable reports, SearchCriteriaBase searchCriteriaBase); + List GetRssDecision(List reports); + List GetSearchDecision(List reports, SearchCriteriaBase searchCriteriaBase); } public class DownloadDecisionMaker : IMakeDownloadDecision @@ -29,18 +30,28 @@ public DownloadDecisionMaker(IEnumerable specifications, IPar _logger = logger; } - public List GetRssDecision(IEnumerable reports) + public List GetRssDecision(List reports) { return GetDecisions(reports).ToList(); } - public List GetSearchDecision(IEnumerable reports, SearchCriteriaBase searchCriteriaBase) + public List GetSearchDecision(List reports, SearchCriteriaBase searchCriteriaBase) { return GetDecisions(reports, searchCriteriaBase).ToList(); } - private IEnumerable GetDecisions(IEnumerable reports, SearchCriteriaBase searchCriteria = null) + private IEnumerable GetDecisions(List reports, SearchCriteriaBase searchCriteria = null) { + if (reports.Any()) + { + _logger.Progress("Processing {0} reports", reports.Count()); + } + + else + { + _logger.Progress("No reports found"); + } + foreach (var report in reports) { DownloadDecision decision = null; diff --git a/NzbDrone.Core/Download/DownloadService.cs b/NzbDrone.Core/Download/DownloadService.cs index 583fdfa1f..2c3d15f5c 100644 --- a/NzbDrone.Core/Download/DownloadService.cs +++ b/NzbDrone.Core/Download/DownloadService.cs @@ -1,4 +1,5 @@ using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Parser.Model; @@ -37,7 +38,7 @@ public void DownloadReport(RemoteEpisode remoteEpisode) downloadClient.DownloadNzb(remoteEpisode); - _logger.Info("Report sent to download client. {0}", downloadTitle); + _logger.Progress("Report sent to download client. {0}", downloadTitle); _messageAggregator.PublishEvent(new EpisodeGrabbedEvent(remoteEpisode)); } } diff --git a/NzbDrone.Core/IndexerSearch/Definitions/SingleEpisodeSearchCriteria.cs b/NzbDrone.Core/IndexerSearch/Definitions/SingleEpisodeSearchCriteria.cs index 371f66bc6..56d110079 100644 --- a/NzbDrone.Core/IndexerSearch/Definitions/SingleEpisodeSearchCriteria.cs +++ b/NzbDrone.Core/IndexerSearch/Definitions/SingleEpisodeSearchCriteria.cs @@ -7,7 +7,7 @@ public class SingleEpisodeSearchCriteria : SearchCriteriaBase public override string ToString() { - return string.Format("[{0} : S{1:00}E{2:00} ]", SceneTitle, SeasonNumber, EpisodeNumber); + return string.Format("[{0} : S{1:00}E{2:00}]", SceneTitle, SeasonNumber, EpisodeNumber); } } } \ No newline at end of file diff --git a/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs b/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs index e62a99836..476178f36 100644 --- a/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs +++ b/NzbDrone.Core/IndexerSearch/EpisodeSearchService.cs @@ -1,4 +1,7 @@ -using NzbDrone.Common.Messaging; +using System.Linq; +using NLog; +using NzbDrone.Common.Instrumentation; +using NzbDrone.Common.Messaging; using NzbDrone.Core.Download; namespace NzbDrone.Core.IndexerSearch @@ -7,17 +10,23 @@ public class EpisodeSearchService : IExecute { private readonly ISearchForNzb _nzbSearchService; private readonly IDownloadApprovedReports _downloadApprovedReports; + private readonly Logger _logger; - public EpisodeSearchService(ISearchForNzb nzbSearchService, IDownloadApprovedReports downloadApprovedReports) + public EpisodeSearchService(ISearchForNzb nzbSearchService, + IDownloadApprovedReports downloadApprovedReports, + Logger logger) { _nzbSearchService = nzbSearchService; _downloadApprovedReports = downloadApprovedReports; + _logger = logger; } public void Execute(EpisodeSearchCommand message) { var decisions = _nzbSearchService.EpisodeSearch(message.EpisodeId); - _downloadApprovedReports.DownloadApproved(decisions); + var downloaded = _downloadApprovedReports.DownloadApproved(decisions); + + _logger.Complete("Episode search completed. {0} reports downloaded.", downloaded.Count); } } } diff --git a/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/NzbDrone.Core/IndexerSearch/NzbSearchService.cs index 7386341d2..b17d9ea55 100644 --- a/NzbDrone.Core/IndexerSearch/NzbSearchService.cs +++ b/NzbDrone.Core/IndexerSearch/NzbSearchService.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Threading.Tasks; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.IndexerSearch.Definitions; @@ -129,9 +130,10 @@ public List SeasonSearch(int seriesId, int seasonNumber) private List Dispatch(Func> searchAction, SearchCriteriaBase criteriaBase) { var indexers = _indexerService.GetAvailableIndexers().ToList(); + + _logger.Progress("Searching {0} indexers for {1}", indexers.Count, criteriaBase); + var reports = new List(); - - var taskList = new List(); var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None); @@ -159,7 +161,7 @@ private List Dispatch(Func> Task.WaitAll(taskList.ToArray()); - _logger.Debug("Total of {0} reports were found for {1} in {2} indexers", reports.Count, criteriaBase, indexers.Count); + _logger.Debug("Total of {0} reports were found for {1} from {2} indexers", reports.Count, criteriaBase, indexers.Count); return _makeDownloadDecision.GetSearchDecision(reports, criteriaBase).ToList(); } diff --git a/NzbDrone.Core/IndexerSearch/SeasonSearchService.cs b/NzbDrone.Core/IndexerSearch/SeasonSearchService.cs index 7572b5b6d..f1a7a1e71 100644 --- a/NzbDrone.Core/IndexerSearch/SeasonSearchService.cs +++ b/NzbDrone.Core/IndexerSearch/SeasonSearchService.cs @@ -1,4 +1,6 @@ -using NzbDrone.Common.Messaging; +using NLog; +using NzbDrone.Common.Instrumentation; +using NzbDrone.Common.Messaging; using NzbDrone.Core.Download; namespace NzbDrone.Core.IndexerSearch @@ -7,17 +9,23 @@ public class SeasonSearchService : IExecute { private readonly ISearchForNzb _nzbSearchService; private readonly IDownloadApprovedReports _downloadApprovedReports; + private readonly Logger _logger; - public SeasonSearchService(ISearchForNzb nzbSearchService, IDownloadApprovedReports downloadApprovedReports) + public SeasonSearchService(ISearchForNzb nzbSearchService, + IDownloadApprovedReports downloadApprovedReports, + Logger logger) { _nzbSearchService = nzbSearchService; _downloadApprovedReports = downloadApprovedReports; + _logger = logger; } public void Execute(SeasonSearchCommand message) { var decisions = _nzbSearchService.SeasonSearch(message.SeriesId, message.SeasonNumber); - _downloadApprovedReports.DownloadApproved(decisions); + var downloaded = _downloadApprovedReports.DownloadApproved(decisions); + + _logger.Complete("Season search completed. {0} reports downloaded.", downloaded.Count); } } } diff --git a/NzbDrone.Core/IndexerSearch/SeriesSearchService.cs b/NzbDrone.Core/IndexerSearch/SeriesSearchService.cs index 89dd7c6c2..14da8c84d 100644 --- a/NzbDrone.Core/IndexerSearch/SeriesSearchService.cs +++ b/NzbDrone.Core/IndexerSearch/SeriesSearchService.cs @@ -1,4 +1,6 @@ using System.Linq; +using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.Download; using NzbDrone.Core.Tv; @@ -10,14 +12,17 @@ public class SeriesSearchService : IExecute private readonly ISeasonService _seasonService; private readonly ISearchForNzb _nzbSearchService; private readonly IDownloadApprovedReports _downloadApprovedReports; + private readonly Logger _logger; public SeriesSearchService(ISeasonService seasonService, ISearchForNzb nzbSearchService, - IDownloadApprovedReports downloadApprovedReports) + IDownloadApprovedReports downloadApprovedReports, + Logger logger) { _seasonService = seasonService; _nzbSearchService = nzbSearchService; _downloadApprovedReports = downloadApprovedReports; + _logger = logger; } public void Execute(SeriesSearchCommand message) @@ -27,11 +32,15 @@ public void Execute(SeriesSearchCommand message) .OrderBy(s => s.SeasonNumber) .ToList(); + var downloadedCount = 0; + foreach (var season in seasons) { var decisions = _nzbSearchService.SeasonSearch(message.SeriesId, season.SeasonNumber); - _downloadApprovedReports.DownloadApproved(decisions); + downloadedCount += _downloadApprovedReports.DownloadApproved(decisions).Count; } + + _logger.Complete("Series search completed. {0} reports downloaded.", downloadedCount); } } } diff --git a/NzbDrone.Core/Indexers/IndexerFetchService.cs b/NzbDrone.Core/Indexers/IndexerFetchService.cs index 2e585f862..cc0eb8691 100644 --- a/NzbDrone.Core/Indexers/IndexerFetchService.cs +++ b/NzbDrone.Core/Indexers/IndexerFetchService.cs @@ -48,7 +48,7 @@ public IList Fetch(IIndexer indexer, SeasonSearchCriteria searchCrit var result = Fetch(indexer, searchCriteria, 0).DistinctBy(c => c.NzbUrl).ToList(); - _logger.Info("Finished searching {0} on {1}. Found {2}", indexer.Name, searchCriteria, result.Count); + _logger.Info("Finished searching {0} for {1}. Found {2}", indexer.Name, searchCriteria, result.Count); return result; } @@ -80,12 +80,10 @@ public IList Fetch(IIndexer indexer, SingleEpisodeSearchCriteria sea var result = Fetch(indexer, searchUrls); - _logger.Info("Finished searching {0} on {1}. Found {2}", indexer.Name, searchCriteria, result.Count); + _logger.Info("Finished searching {0} for {1}. Found {2}", indexer.Name, searchCriteria, result.Count); return result; - } - public IList Fetch(IIndexer indexer, DailyEpisodeSearchCriteria searchCriteria) { _logger.Debug("Searching for {0}", searchCriteria); @@ -93,7 +91,7 @@ public IList Fetch(IIndexer indexer, DailyEpisodeSearchCriteria sear var searchUrls = indexer.GetDailyEpisodeSearchUrls(searchCriteria.QueryTitle, searchCriteria.SeriesTvRageId, searchCriteria.Airtime); var result = Fetch(indexer, searchUrls); - _logger.Info("Finished searching {0} on {1}. Found {2}", indexer.Name, searchCriteria, result.Count); + _logger.Info("Finished searching {0} for {1}. Found {2}", indexer.Name, searchCriteria, result.Count); return result; } diff --git a/NzbDrone.Core/Indexers/RssSyncService.cs b/NzbDrone.Core/Indexers/RssSyncService.cs index dcbf340b1..3362bcc56 100644 --- a/NzbDrone.Core/Indexers/RssSyncService.cs +++ b/NzbDrone.Core/Indexers/RssSyncService.cs @@ -33,13 +33,13 @@ public RssSyncService(IFetchAndParseRss rssFetcherAndParser, public void Sync() { - _logger.Info("Starting RSS Sync"); + _logger.Progress("Starting RSS Sync"); var reports = _rssFetcherAndParser.Fetch(); var decisions = _downloadDecisionMaker.GetRssDecision(reports); - var qualifiedReports = _downloadApprovedReports.DownloadApproved(decisions); + var downloaded = _downloadApprovedReports.DownloadApproved(decisions); - _logger.Complete("RSS Sync Completed. Reports found: {0}, Reports downloaded: {1}", reports.Count, qualifiedReports.Count()); + _logger.Complete("RSS Sync Completed. Reports found: {0}, Reports downloaded: {1}", reports.Count, downloaded.Count()); } public void Execute(RssSyncCommand message) diff --git a/NzbDrone.Core/MediaFiles/DiskScanService.cs b/NzbDrone.Core/MediaFiles/DiskScanService.cs index 0fb6901fe..fc5aade8e 100644 --- a/NzbDrone.Core/MediaFiles/DiskScanService.cs +++ b/NzbDrone.Core/MediaFiles/DiskScanService.cs @@ -3,6 +3,7 @@ using System.Linq; using NLog; using NzbDrone.Common; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.MediaFiles.Commands; using NzbDrone.Core.MediaFiles.EpisodeImport; @@ -52,6 +53,7 @@ public DiskScanService(IDiskProvider diskProvider, private void Scan(Series series) { + _logger.Progress("Starting disk scan for {0}", series.Title); _messageAggregator.PublishCommand(new CleanMediaFileDb(series.Id)); if (!_diskProvider.FolderExists(series.Path)) @@ -64,6 +66,8 @@ private void Scan(Series series) var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, series, false); _importApprovedEpisodes.Import(decisions); + + _logger.Complete("Completed disk scan for {0}", series.Title); } public string[] GetVideoFiles(string path, bool allDirectories = true) diff --git a/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs b/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs index 7912039e7..5a3dc563e 100644 --- a/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs +++ b/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.MediaFiles.Commands; using NzbDrone.Core.MediaFiles.Events; @@ -67,9 +68,9 @@ public void Execute(RenameSeasonCommand message) var series = _seriesService.GetSeries(message.SeriesId); var episodeFiles = _mediaFileService.GetFilesBySeason(message.SeriesId, message.SeasonNumber); - _logger.Info("Renaming {0} files for {1} season {2}", episodeFiles.Count, series.Title, message.SeasonNumber); + _logger.Progress("Renaming {0} files for {1} season {2}", episodeFiles.Count, series.Title, message.SeasonNumber); RenameFiles(episodeFiles, series); - _logger.Debug("Episode Fies renamed for {0} season {1}", series.Title, message.SeasonNumber); + _logger.Complete("Episode Fies renamed for {0} season {1}", series.Title, message.SeasonNumber); } public void Execute(RenameSeriesCommand message) @@ -77,9 +78,9 @@ public void Execute(RenameSeriesCommand message) var series = _seriesService.GetSeries(message.SeriesId); var episodeFiles = _mediaFileService.GetFilesBySeries(message.SeriesId); - _logger.Info("Renaming {0} files for {1}", episodeFiles.Count, series.Title); + _logger.Progress("Renaming {0} files for {1}", episodeFiles.Count, series.Title); RenameFiles(episodeFiles, series); - _logger.Debug("Episode Fies renamed for {0}", series.Title); + _logger.Complete("Episode Fies renamed for {0}", series.Title); } } } diff --git a/NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs b/NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs index ee99f7599..d11d33bd0 100644 --- a/NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs +++ b/NzbDrone.Core/ProgressMessaging/ProgressMessageTarget.cs @@ -56,7 +56,12 @@ protected override void Write(LogEventInfo logEvent) return; } - var status = logEvent.Properties.ContainsKey("Status") ? (ProcessState)logEvent.Properties["Status"] : ProcessState.Running; + if (!logEvent.Properties.ContainsKey("Status")) + { + return; + } + + var status = (ProcessState)logEvent.Properties["Status"]; var message = new ProgressMessage(); message.Time = logEvent.TimeStamp; diff --git a/NzbDrone.Core/Tv/EpisodeService.cs b/NzbDrone.Core/Tv/EpisodeService.cs index 7747510d8..11a345c46 100644 --- a/NzbDrone.Core/Tv/EpisodeService.cs +++ b/NzbDrone.Core/Tv/EpisodeService.cs @@ -129,7 +129,7 @@ public void SetEpisodeMonitored(int episodeId, bool monitored) var episode = _episodeRepository.Get(episodeId); _episodeRepository.SetMonitoredFlat(episode, monitored); - logger.Info("Monitored flag for Episode:{0} was set to {1}", episodeId, monitored); + logger.Debug("Monitored flag for Episode:{0} was set to {1}", episodeId, monitored); } public void SetEpisodeMonitoredBySeason(int seriesId, int seasonNumber, bool monitored) diff --git a/NzbDrone.Core/Tv/RefreshEpisodeService.cs b/NzbDrone.Core/Tv/RefreshEpisodeService.cs index c62d8a5d2..6c2e1c4b0 100644 --- a/NzbDrone.Core/Tv/RefreshEpisodeService.cs +++ b/NzbDrone.Core/Tv/RefreshEpisodeService.cs @@ -30,7 +30,7 @@ public RefreshEpisodeService(IEpisodeService episodeService, public void RefreshEpisodeInfo(Series series, IEnumerable remoteEpisodes) { - _logger.Info("Starting series info refresh for: {0}", series); + _logger.Info("Starting episode info refresh for: {0}", series); var successCount = 0; var failCount = 0; diff --git a/NzbDrone.Core/Tv/RefreshSeriesService.cs b/NzbDrone.Core/Tv/RefreshSeriesService.cs index bbdb8e472..6e9f38dda 100644 --- a/NzbDrone.Core/Tv/RefreshSeriesService.cs +++ b/NzbDrone.Core/Tv/RefreshSeriesService.cs @@ -2,6 +2,7 @@ using System.IO; using System.Linq; using NLog; +using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Messaging; using NzbDrone.Core.DataAugmentation.DailySeries; using NzbDrone.Core.MetadataSource; @@ -30,39 +31,9 @@ public RefreshSeriesService(IProvideSeriesInfo seriesInfo, ISeriesService series _logger = logger; } - - public void Execute(RefreshSeriesCommand message) - { - if (message.SeriesId.HasValue) - { - var series = _seriesService.GetSeries(message.SeriesId.Value); - RefreshSeriesInfo(series); - } - else - { - var allSeries = _seriesService.GetAllSeries().OrderBy(c => c.LastInfoSync).ToList(); - - foreach (var series in allSeries) - { - try - { - RefreshSeriesInfo(series); - } - catch (Exception e) - { - _logger.ErrorException("Couldn't refresh info for {0}".Inject(series), e); - } - } - } - } - - public void HandleAsync(SeriesAddedEvent message) - { - RefreshSeriesInfo(message.Series); - } - private void RefreshSeriesInfo(Series series) { + _logger.Progress("Starting Series Refresh for {0}", series.Title); var tuple = _seriesInfo.GetSeriesInfo(series.TvdbId); var seriesInfo = tuple.Item1; @@ -96,7 +67,38 @@ private void RefreshSeriesInfo(Series series) _seriesService.UpdateSeries(series); _refreshEpisodeService.RefreshEpisodeInfo(series, tuple.Item2); + _logger.Complete("Finished series refresh for {0}", series.Title); _messageAggregator.PublishEvent(new SeriesUpdatedEvent(series)); } + + public void Execute(RefreshSeriesCommand message) + { + if (message.SeriesId.HasValue) + { + var series = _seriesService.GetSeries(message.SeriesId.Value); + RefreshSeriesInfo(series); + } + else + { + var allSeries = _seriesService.GetAllSeries().OrderBy(c => c.LastInfoSync).ToList(); + + foreach (var series in allSeries) + { + try + { + RefreshSeriesInfo(series); + } + catch (Exception e) + { + _logger.ErrorException("Couldn't refresh info for {0}".Inject(series), e); + } + } + } + } + + public void HandleAsync(SeriesAddedEvent message) + { + RefreshSeriesInfo(message.Series); + } } } \ No newline at end of file diff --git a/UI/Episode/Search/Layout.js b/UI/Episode/Search/Layout.js index aa24febf5..61f101ac7 100644 --- a/UI/Episode/Search/Layout.js +++ b/UI/Episode/Search/Layout.js @@ -46,12 +46,11 @@ define( var message = seriesTitle + ' - ' + season + 'x' + FormatHelpers.pad(episode, 2); Actioneer.ExecuteCommand({ - command : 'episodeSearch', - properties : { + command : 'episodeSearch', + properties: { episodeId: this.model.get('id') }, - errorMessage: 'Search failed for: ' + message, - startMessage: 'Search started for: ' + message + errorMessage: 'Search failed for: ' + message }); App.vent.trigger(App.Commands.CloseModalCommand); diff --git a/UI/ProgressMessaging/ProgressMessageCollection.js b/UI/ProgressMessaging/ProgressMessageCollection.js index eb7317b4d..58a5da850 100644 --- a/UI/ProgressMessaging/ProgressMessageCollection.js +++ b/UI/ProgressMessaging/ProgressMessageCollection.js @@ -17,11 +17,13 @@ define( collection.signalRconnection.received(function (message) { var type = getMessengerType(message.status); + var hideAfter = type === 'info' ? 60 : 5; Messenger.show({ - id : message.commandId, - message: message.message, - type : type + id : message.commandId, + message : message.message, + type : type, + hideAfter: hideAfter }); }); diff --git a/UI/Shared/Actioneer.js b/UI/Shared/Actioneer.js index 516a0e7b7..847e8cec4 100644 --- a/UI/Shared/Actioneer.js +++ b/UI/Shared/Actioneer.js @@ -92,6 +92,10 @@ define( }, _getIconClass: function(element) { + if (!element) { + return ''; + } + return element.attr('class').match(/(?:^|\s)icon\-.+?(?:$|\s)/)[0]; }, @@ -143,14 +147,16 @@ define( options.button.removeClass('disable'); } - if (options.leaveIcon) { - options.element.removeClass('icon-spin'); - } + if (options.element) { + if (options.leaveIcon) { + options.element.removeClass('icon-spin'); + } - else { - options.element.addClass(options.iconClass); - options.element.removeClass('icon-nd-spinner'); - options.element.removeClass('icon-spin'); + else { + options.element.addClass(options.iconClass); + options.element.removeClass('icon-nd-spinner'); + options.element.removeClass('icon-spin'); + } } if (options.always) { From 1166a81eb39e547a8dc12a8a13260856fe143d60 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 3 Sep 2013 22:02:26 -0700 Subject: [PATCH 023/131] Chained commands keep the same CommandId in nlog context --- NzbDrone.Common/Messaging/MessageAggregator.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index b8ebd3690..750e7d9cd 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -145,7 +145,10 @@ private void ExecuteCommand(TrackedCommand trackedCommand) where TComm try { - MappedDiagnosticsContext.Set("CommandId", trackedCommand.Command.CommandId); + if (!MappedDiagnosticsContext.Contains("CommandId")) + { + MappedDiagnosticsContext.Set("CommandId", trackedCommand.Command.CommandId); + } PublishEvent(new CommandStartedEvent(trackedCommand)); handler.Execute(command); From d5e1be39f1d747e4eb2ec9f5def4da896dd116a9 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 3 Sep 2013 22:02:58 -0700 Subject: [PATCH 024/131] SignalR disconnect timeout is now 5 minutes instead of 30 seconds --- NzbDrone.Host/Owin/MiddleWare/SignalRMiddleWare.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NzbDrone.Host/Owin/MiddleWare/SignalRMiddleWare.cs b/NzbDrone.Host/Owin/MiddleWare/SignalRMiddleWare.cs index ba9a436fa..61c7cd92a 100644 --- a/NzbDrone.Host/Owin/MiddleWare/SignalRMiddleWare.cs +++ b/NzbDrone.Host/Owin/MiddleWare/SignalRMiddleWare.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Microsoft.AspNet.SignalR; using NzbDrone.Api.SignalR; @@ -17,6 +18,8 @@ public SignalRMiddleWare(IEnumerable persistentCon _persistentConnections = persistentConnections; SignalrDependencyResolver.Register(container); + + GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(300000); } public void Attach(IAppBuilder appBuilder) From b2ab9c154767d8bbbcc5491596b09203692a22b1 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 4 Sep 2013 11:05:28 -0700 Subject: [PATCH 025/131] QualityParserFixture improvements, m2ts will default to HDTV720p --- .../ParserTests/QualityParserFixture.cs | 272 +++++++----------- NzbDrone.Core/Parser/QualityParser.cs | 2 + 2 files changed, 102 insertions(+), 172 deletions(-) diff --git a/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs b/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs index a1a8c60f0..6aed1581c 100644 --- a/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs +++ b/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs @@ -1,6 +1,4 @@ - - -using System; +using System; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Qualities; @@ -12,120 +10,6 @@ namespace NzbDrone.Core.Test.ParserTests public class QualityParserFixture : CoreTest { - public static object[] SdtvCases = - { - new object[] { "S07E23 .avi ", false }, - new object[] {"The.Shield.S01E13.x264-CtrlSD", false}, - new object[] { "Nikita S02E01 HDTV XviD 2HD", false }, - new object[] { "Gossip Girl S05E11 PROPER HDTV XviD 2HD", true }, - new object[] { "The Jonathan Ross Show S02E08 HDTV x264 FTP", false }, - new object[] { "White.Van.Man.2011.S02E01.WS.PDTV.x264-TLA", false }, - new object[] { "White.Van.Man.2011.S02E01.WS.PDTV.x264-REPACK-TLA", true }, - new object[] { "The Real Housewives of Vancouver S01E04 DSR x264 2HD", false }, - new object[] { "Vanguard S01E04 Mexicos Death Train DSR x264 MiNDTHEGAP", false }, - new object[] { "Chuck S11E03 has no periods or extension HDTV", false }, - new object[] { "Chuck.S04E05.HDTV.XviD-LOL", false }, - new object[] { "Sonny.With.a.Chance.S02E15.avi", false }, - new object[] { "Sonny.With.a.Chance.S02E15.xvid", false }, - new object[] { "Sonny.With.a.Chance.S02E15.divx", false }, - new object[] { "The.Girls.Next.Door.S03E06.HDTV-WiDE", false }, - new object[] { "Degrassi.S10E27.WS.DSR.XviD-2HD", false }, - }; - - public static object[] DvdCases = - { - new object[] { "WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3-REPACK.-HELLYWOOD.avi", true }, - new object[] { "The.Shield.S01E13.NTSC.x264-CtrlSD", false }, - new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", false }, - new object[] { "WEEDS.S03E01-06.DUAL.BDRip.X-viD.AC3.-HELLYWOOD", false }, - new object[] { "WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", false }, - new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false }, - new object[] { "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false }, - new object[] { "WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3.-HELLYWOOD.avi", false }, - new object[] { "The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", false }, - new object[] { "The.Girls.Next.Door.S03E06.DVD.Rip.XviD-WiDE", false }, - new object[] { "the.shield.1x13.circles.ws.xvidvd-tns", false} - }; - - public static object[] Webdl480pCases = - { - new object[] { "Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", false }, - new object[] { "Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", false }, - new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false }, - }; - - public static object[] Hdtv720pCases = - { - new object[] { "Dexter - S01E01 - Title [HDTV]", false }, - new object[] { "Dexter - S01E01 - Title [HDTV-720p]", false }, - new object[] { "Pawn Stars S04E87 REPACK 720p HDTV x264 aAF", true }, - new object[] { "Sonny.With.a.Chance.S02E15.720p", false }, - new object[] { "S07E23 - [HDTV-720p].mkv ", false }, - new object[] { "Chuck - S22E03 - MoneyBART - HD TV.mkv", false }, - new object[] { "S07E23.mkv ", false }, - new object[] { "Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", false }, - new object[] { "Sonny.With.a.Chance.S02E15.mkv", false }, - }; - - public static object[] Hdtv1080pCases = - { - new object[] { "Under the Dome S01E10 Let the Games Begin 1080p", false }, - new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.X264-QCF", false }, - new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.x264-QCF", false }, - new object[] { "DEXTER.S07E01.ARE.YOU.1080P.HDTV.proper.X264-QCF", true }, - new object[] { "Dexter - S01E01 - Title [HDTV-1080p]", false }, - }; - - public static object[] Webdl720pCases = - { - new object[] { "Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", false }, - new object[] { "Vanguard S01E04 Mexicos Death Train 720p WEB DL", false }, - new object[] { "Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", false }, - new object[] { "Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", false }, - new object[] { "Chuck - S11E06 - D-Yikes! - 720p WEB-DL.mkv", false }, - new object[] { "Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", false }, - new object[] { "S07E23 - [WEBDL].mkv ", false }, - new object[] { "Fringe S04E22 720p WEB-DL DD5.1 H264-EbP.mkv", false }, - }; - - public static object[] Webdl1080pCases = - { - new object[] { "Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", false }, - new object[] { "CSI NY S09E03 1080p WEB DL DD5 1 H264 NFHD", false }, - new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 NFHD", false }, - new object[] { "Criminal.Minds.S08E01.1080p.WEB-DL.DD5.1.H264-NFHD", false }, - new object[] { "Its.Always.Sunny.in.Philadelphia.S08E01.1080p.WEB-DL.proper.AAC2.0.H.264", true }, - new object[] { "Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 REPACK NFHD", true }, - new object[] { "Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", false }, - new object[] { "The.Big.Bang.Theory.S06E11.The.Santa.Simulation.1080p.WEB-DL.DD5.1.H.264", false }, - }; - - public static object[] Bluray720pCases = - { - new object[] { "WEEDS.S03E01-06.DUAL.Bluray.AC3.-HELLYWOOD.avi", false }, - new object[] { "Chuck - S01E03 - Come Fly With Me - 720p BluRay.mkv", false }, - }; - - public static object[] Bluray1080pCases = - { - new object[] { "Chuck - S01E03 - Come Fly With Me - 1080p BluRay.mkv", false }, - new object[] { "Sons.Of.Anarchy.S02E13.1080p.BluRay.x264-AVCDVD", false }, - }; - - public static object[] RawCases = - { - new object[] { "POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false }, - new object[] { "How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", false }, - new object[] { "The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", false }, - }; - - public static object[] UnknownCases = - { - new object[] { "Sonny.With.a.Chance.S02E15", false }, - new object[] { "Law & Order: Special Victims Unit - 11x11 - Quickie", false }, - - }; - public static object[] SelfQualityParserCases = { new object[] { Quality.SDTV }, @@ -138,92 +22,129 @@ public class QualityParserFixture : CoreTest new object[] { Quality.Bluray1080p } }; - [Test, TestCaseSource("SdtvCases")] - public void should_parse_sdtv_quality(string postTitle, bool proper) + [TestCase("S07E23 .avi ", false)] + [TestCase("The.Shield.S01E13.x264-CtrlSD", false)] + [TestCase("Nikita S02E01 HDTV XviD 2HD", false)] + [TestCase("Gossip Girl S05E11 PROPER HDTV XviD 2HD", true)] + [TestCase("The Jonathan Ross Show S02E08 HDTV x264 FTP", false)] + [TestCase("White.Van.Man.2011.S02E01.WS.PDTV.x264-TLA", false)] + [TestCase("White.Van.Man.2011.S02E01.WS.PDTV.x264-REPACK-TLA", true)] + [TestCase("The Real Housewives of Vancouver S01E04 DSR x264 2HD", false)] + [TestCase("Vanguard S01E04 Mexicos Death Train DSR x264 MiNDTHEGAP", false)] + [TestCase("Chuck S11E03 has no periods or extension HDTV", false)] + [TestCase("Chuck.S04E05.HDTV.XviD-LOL", false)] + [TestCase("Sonny.With.a.Chance.S02E15.avi", false)] + [TestCase("Sonny.With.a.Chance.S02E15.xvid", false)] + [TestCase("Sonny.With.a.Chance.S02E15.divx", false)] + [TestCase("The.Girls.Next.Door.S03E06.HDTV-WiDE", false)] + [TestCase("Degrassi.S10E27.WS.DSR.XviD-2HD", false)] + public void should_parse_sdtv_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.SDTV); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.SDTV, proper); } - [Test, TestCaseSource("DvdCases")] - public void should_parse_dvd_quality(string postTitle, bool proper) + [TestCase("WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3-REPACK.-HELLYWOOD.avi", true)] + [TestCase("The.Shield.S01E13.NTSC.x264-CtrlSD", false)] + [TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", false)] + [TestCase("WEEDS.S03E01-06.DUAL.BDRip.X-viD.AC3.-HELLYWOOD", false)] + [TestCase("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", false)] + [TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false)] + [TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false)] + [TestCase("WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3.-HELLYWOOD.avi", false)] + [TestCase("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", false)] + [TestCase("The.Girls.Next.Door.S03E06.DVD.Rip.XviD-WiDE", false)] + [TestCase("the.shield.1x13.circles.ws.xvidvd-tns", false)] + public void should_parse_dvd_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.DVD); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.DVD, proper); } - [Test, TestCaseSource("Webdl480pCases")] - public void should_parse_webdl480p_quality(string postTitle, bool proper) + [TestCase("Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", false)] + [TestCase("Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", false)] + [TestCase("The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false)] + public void should_parse_webdl480p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.WEBDL480p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.WEBDL480p, proper); } - [Test, TestCaseSource("Hdtv720pCases")] - public void should_parse_hdtv720p_quality(string postTitle, bool proper) + [TestCase("Dexter - S01E01 - Title [HDTV]", false)] + [TestCase("Dexter - S01E01 - Title [HDTV-720p]", false)] + [TestCase("Pawn Stars S04E87 REPACK 720p HDTV x264 aAF", true)] + [TestCase("Sonny.With.a.Chance.S02E15.720p", false)] + [TestCase("S07E23 - [HDTV-720p].mkv ", false)] + [TestCase("Chuck - S22E03 - MoneyBART - HD TV.mkv", false)] + [TestCase("S07E23.mkv ", false)] + [TestCase("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", false)] + [TestCase("Sonny.With.a.Chance.S02E15.mkv", false)] + [TestCase("The Big Bang Theory.S03E01.The Electric Can Opener Fluctuation.m2ts", false)] + public void should_parse_hdtv720p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.HDTV720p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.HDTV720p, proper); } - [Test, TestCaseSource("Hdtv1080pCases")] - public void should_parse_hdtv1080p_quality(string postTitle, bool proper) + [TestCase("Under the Dome S01E10 Let the Games Begin 1080p", false)] + [TestCase("DEXTER.S07E01.ARE.YOU.1080P.HDTV.X264-QCF", false)] + [TestCase("DEXTER.S07E01.ARE.YOU.1080P.HDTV.x264-QCF", false)] + [TestCase("DEXTER.S07E01.ARE.YOU.1080P.HDTV.proper.X264-QCF", true)] + [TestCase("Dexter - S01E01 - Title [HDTV-1080p]", false)] + public void should_parse_hdtv1080p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.HDTV1080p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.HDTV1080p, proper); } - [Test, TestCaseSource("Webdl720pCases")] - public void should_parse_webdl720p_quality(string postTitle, bool proper) + [TestCase("Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", false)] + [TestCase("Vanguard S01E04 Mexicos Death Train 720p WEB DL", false)] + [TestCase("Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", false)] + [TestCase("Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", false)] + [TestCase("Chuck - S11E06 - D-Yikes! - 720p WEB-DL.mkv", false)] + [TestCase("Sonny.With.a.Chance.S02E15.720p.WEB-DL.DD5.1.H.264-SURFER", false)] + [TestCase("S07E23 - [WEBDL].mkv ", false)] + [TestCase("Fringe S04E22 720p WEB-DL DD5.1 H264-EbP.mkv", false)] + public void should_parse_webdl720p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.WEBDL720p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.WEBDL720p, proper); } - [Test, TestCaseSource("Webdl1080pCases")] - public void should_parse_webdl1080p_quality(string postTitle, bool proper) + [TestCase("Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", false)] + [TestCase("CSI NY S09E03 1080p WEB DL DD5 1 H264 NFHD", false)] + [TestCase("Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 NFHD", false)] + [TestCase("Criminal.Minds.S08E01.1080p.WEB-DL.DD5.1.H264-NFHD", false)] + [TestCase("Its.Always.Sunny.in.Philadelphia.S08E01.1080p.WEB-DL.proper.AAC2.0.H.264", true)] + [TestCase("Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 REPACK NFHD", true)] + [TestCase("Glee.S04E09.Swan.Song.1080p.WEB-DL.DD5.1.H.264-ECI", false)] + [TestCase("The.Big.Bang.Theory.S06E11.The.Santa.Simulation.1080p.WEB-DL.DD5.1.H.264", false)] + public void should_parse_webdl1080p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.WEBDL1080p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.WEBDL1080p, proper); } - [Test, TestCaseSource("Bluray720pCases")] - public void should_parse_bluray720p_quality(string postTitle, bool proper) + [TestCase("WEEDS.S03E01-06.DUAL.Bluray.AC3.-HELLYWOOD.avi", false)] + [TestCase("Chuck - S01E03 - Come Fly With Me - 720p BluRay.mkv", false)] + public void should_parse_bluray720p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.Bluray720p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.Bluray720p, proper); } - [Test, TestCaseSource("Bluray1080pCases")] - public void should_parse_bluray1080p_quality(string postTitle, bool proper) + [TestCase("Chuck - S01E03 - Come Fly With Me - 1080p BluRay.mkv", false)] + [TestCase("Sons.Of.Anarchy.S02E13.1080p.BluRay.x264-AVCDVD", false)] + public void should_parse_bluray1080p_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.Bluray1080p); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.Bluray1080p, proper); } - [Test, TestCaseSource("RawCases")] - public void should_parse_raw_quality(string postTitle, bool proper) + [TestCase("POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false)] + [TestCase("How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", false)] + [TestCase("The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", false)] + public void should_parse_raw_quality(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.RAWHD); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.RAWHD, proper); } - [Test, TestCaseSource("UnknownCases")] - public void quality_parse(string postTitle, bool proper) + [TestCase("Sonny.With.a.Chance.S02E15", false)] + [TestCase("Law & Order: Special Victims Unit - 11x11 - Quickie", false)] + public void quality_parse(string title, bool proper) { - var result = Parser.QualityParser.ParseQuality(postTitle); - result.Quality.Should().Be(Quality.Unknown); - result.Proper.Should().Be(proper); + ParseAndVerifyQuality(title, Quality.Unknown, proper); } [Test, TestCaseSource("SelfQualityParserCases")] @@ -233,5 +154,12 @@ public void parsing_our_own_quality_enum(Quality quality) var result = Parser.QualityParser.ParseQuality(fileName); result.Quality.Should().Be(quality); } + + private void ParseAndVerifyQuality(string title, Quality quality, bool proper) + { + var result = Parser.QualityParser.ParseQuality(title); + result.Quality.Should().Be(quality); + result.Proper.Should().Be(proper); + } } } diff --git a/NzbDrone.Core/Parser/QualityParser.cs b/NzbDrone.Core/Parser/QualityParser.cs index 8cd3077e2..4627f27d0 100644 --- a/NzbDrone.Core/Parser/QualityParser.cs +++ b/NzbDrone.Core/Parser/QualityParser.cs @@ -168,12 +168,14 @@ public static QualityModel ParseQuality(string name) case ".dvr-ms": case ".ogm": case ".strm": + { result.Quality = Quality.SDTV; break; } case ".mkv": case ".ts": + case ".m2ts": { result.Quality = Quality.HDTV720p; break; From f00c0f0cca7e1ba96bd28be76b83cab77d4a6d2c Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 4 Sep 2013 17:24:46 -0700 Subject: [PATCH 026/131] Actioneer won't blow up after saving model --- UI/Shared/Actioneer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UI/Shared/Actioneer.js b/UI/Shared/Actioneer.js index 847e8cec4..de9fcef8f 100644 --- a/UI/Shared/Actioneer.js +++ b/UI/Shared/Actioneer.js @@ -38,6 +38,8 @@ define( }, _handlePromise: function (promise, options) { + var self = this; + promise.done(function () { self._onSuccess(options); }); From 4bcd5ce5c6aa1adb8b626b1e95bacf933a3c4830 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 4 Sep 2013 22:01:22 -0700 Subject: [PATCH 027/131] Removed season menu in favour of minimizing seasons --- UI/Content/theme.less | 4 +- UI/Series/Details/SeasonLayout.js | 76 +++++++++++++--- UI/Series/Details/SeasonLayoutTemplate.html | 13 ++- .../Details/SeasonMenu/CollectionView.js | 31 ------- UI/Series/Details/SeasonMenu/ItemView.js | 88 ------------------- .../Details/SeasonMenu/ItemViewTemplate.html | 14 --- UI/Series/Details/SeriesDetailsLayout.js | 8 -- UI/Series/Details/SeriesDetailsTemplate.html | 3 - UI/Series/Index/EpisodeProgressPartial.html | 6 +- UI/Series/series.less | 26 ++---- 10 files changed, 91 insertions(+), 178 deletions(-) delete mode 100644 UI/Series/Details/SeasonMenu/CollectionView.js delete mode 100644 UI/Series/Details/SeasonMenu/ItemView.js delete mode 100644 UI/Series/Details/SeasonMenu/ItemViewTemplate.html diff --git a/UI/Content/theme.less b/UI/Content/theme.less index 4c8c3a1e8..5e94c3bd3 100644 --- a/UI/Content/theme.less +++ b/UI/Content/theme.less @@ -12,7 +12,7 @@ @import "../Shared/Styles/clickable"; @import "../Shared/Styles/card"; -.progress { +.progress.episode-progress { width : 125px; position : relative; margin-bottom : 2px; @@ -21,6 +21,7 @@ font-size : 11.844px; font-weight : bold; text-align : center; + cursor : default; } .progressbar-back-text { @@ -33,6 +34,7 @@ display : block; width : 125px; } + .bar { position : absolute; overflow : hidden; diff --git a/UI/Series/Details/SeasonLayout.js b/UI/Series/Details/SeasonLayout.js index b5281541f..621223a98 100644 --- a/UI/Series/Details/SeasonLayout.js +++ b/UI/Series/Details/SeasonLayout.js @@ -8,8 +8,9 @@ define( 'Cells/EpisodeTitleCell', 'Cells/RelativeDateCell', 'Cells/EpisodeStatusCell', - 'Shared/Actioneer' - ], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, Actioneer) { + 'Shared/Actioneer', + 'moment' + ], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, Actioneer, Moment) { return Marionette.Layout.extend({ template: 'Series/Details/SeasonLayoutTemplate', @@ -20,13 +21,15 @@ define( }, events: { - 'click .x-season-search' : '_seasonSearch', - 'click .x-season-monitored': '_seasonMonitored', - 'click .x-season-rename' : '_seasonRename' + 'click .x-season-search' : '_seasonSearch', + 'click .x-season-monitored' : '_seasonMonitored', + 'click .x-season-rename' : '_seasonRename', + 'click .x-show-hide-episodes' : '_showHideEpisodes', + 'dblclick .series-season h2' : '_showHideEpisodes' }, regions: { - episodeGrid: '#x-episode-grid' + episodeGrid: '.x-episode-grid' }, columns: @@ -67,6 +70,8 @@ define( } ], + templateHelpers: {}, + initialize: function (options) { if (!options.episodeCollection) { @@ -76,6 +81,9 @@ define( this.episodeCollection = options.episodeCollection.bySeason(this.model.get('seasonNumber')); this.series = options.series; + this.showingEpisodes = this._shouldShowEpisodes(); + this.templateHelpers.showingEpisodes = this.showingEpisodes; + this.listenTo(this.model, 'sync', function () { this._afterSeasonMonitored(); }, this); @@ -86,11 +94,9 @@ define( }, onRender: function () { - this.episodeGrid.show(new Backgrid.Grid({ - columns : this.columns, - collection: this.episodeCollection, - className : 'table table-hover season-grid' - })); + if (this.showingEpisodes) { + this._showEpisodes(); + } this._setSeasonMonitoredState(); }, @@ -159,6 +165,54 @@ define( _afterRename: function () { App.vent.trigger(App.Events.SeasonRenamed, { series: this.series, seasonNumber: this.model.get('seasonNumber') }); + }, + + _showEpisodes: function () { + this.episodeGrid.show(new Backgrid.Grid({ + columns : this.columns, + collection: this.episodeCollection, + className : 'table table-hover season-grid' + })); + }, + + _shouldShowEpisodes: function () { + var startDate = Moment().add('month', -1); + var endDate = Moment().add('year', 1); + + var result = this.episodeCollection.some(function(episode) { + + var airDate = episode.get('airDateUtc'); + + if (airDate) + { + var airDateMoment = Moment(airDate); + + if (airDateMoment.isAfter(startDate) && airDateMoment.isBefore(endDate)) { + return true; + } + } + + return false; + }); + + return result; + }, + + _showHideEpisodes: function () { + if (this.showingEpisodes) { + this.showingEpisodes = false; + this.episodeGrid.$el.slideUp(); + this.episodeGrid.close(); + } + + else { + this.showingEpisodes = true; + this._showEpisodes(); + this.episodeGrid.$el.slideDown(); + } + + this.templateHelpers.showingEpisodes = this.showingEpisodes; + this.render(); } }); }); diff --git a/UI/Series/Details/SeasonLayoutTemplate.html b/UI/Series/Details/SeasonLayoutTemplate.html index eb02bf938..372caf157 100644 --- a/UI/Series/Details/SeasonLayoutTemplate.html +++ b/UI/Series/Details/SeasonLayoutTemplate.html @@ -1,15 +1,26 @@ 

+ {{#if seasonNumber}} Season {{seasonNumber}} {{else}} Specials {{/if}} +

-
+
+
+

+ {{#if showingEpisodes}} +