diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs new file mode 100644 index 000000000..e3d30bf20 --- /dev/null +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NzbDrone.Api.Extensions; +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Api.Commands +{ + public class CommandModule : NzbDroneRestModule + { + private readonly IMessageAggregator _messageAggregator; + private readonly IEnumerable _commands; + + public CommandModule(IMessageAggregator messageAggregator, IEnumerable commands) + { + _messageAggregator = messageAggregator; + _commands = commands; + + CreateResource = RunCommand; + } + + private CommandResource RunCommand(CommandResource resource) + { + var commandType = _commands.Single(c => c.GetType().Name.Replace("Command", "").Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase)) + .GetType(); + var command = (object)Request.Body.FromJson(commandType); + var method = typeof(IMessageAggregator).GetMethod("PublishCommand"); + var genericMethod = method.MakeGenericMethod(commandType); + genericMethod.Invoke(_messageAggregator, new[] { command }); + + return resource; + + } + } +} \ No newline at end of file diff --git a/NzbDrone.Api/Commands/CommandResource.cs b/NzbDrone.Api/Commands/CommandResource.cs new file mode 100644 index 000000000..e71a0d08f --- /dev/null +++ b/NzbDrone.Api/Commands/CommandResource.cs @@ -0,0 +1,9 @@ +using NzbDrone.Api.REST; + +namespace NzbDrone.Api.Commands +{ + public class CommandResource : RestResource + { + public string Command { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Api/Extensions/RequestExtensions.cs b/NzbDrone.Api/Extensions/RequestExtensions.cs index 861e59f70..4b17a247d 100644 --- a/NzbDrone.Api/Extensions/RequestExtensions.cs +++ b/NzbDrone.Api/Extensions/RequestExtensions.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using Nancy; using Nancy.Responses; using NzbDrone.Common; @@ -11,11 +12,16 @@ namespace NzbDrone.Api.Extensions private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer(Serializer); public static T FromJson(this Stream body) where T : class, new() + { + return FromJson(body, typeof(T)); + } + + public static T FromJson(this Stream body, Type type) { var reader = new StreamReader(body, true); body.Position = 0; var value = reader.ReadToEnd(); - return Serializer.Deserialize(value); + return (T)Serializer.Deserialize(value, type); } public static JsonResponse AsResponse(this TModel model, HttpStatusCode statusCode = HttpStatusCode.OK) diff --git a/NzbDrone.Api/NancyBootstrapper.cs b/NzbDrone.Api/NancyBootstrapper.cs index b295d64c6..f334b7c1f 100644 --- a/NzbDrone.Api/NancyBootstrapper.cs +++ b/NzbDrone.Api/NancyBootstrapper.cs @@ -30,7 +30,7 @@ namespace NzbDrone.Api AutomapperBootstraper.InitializeAutomapper(); RegisterReporting(container); - container.Resolve().Publish(new ApplicationStartedEvent()); + container.Resolve().PublishEvent(new ApplicationStartedEvent()); ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve().HandleException); } @@ -73,7 +73,7 @@ namespace NzbDrone.Api public void Shutdown() { - ApplicationContainer.Resolve().Publish(new ApplicationShutdownRequested()); + ApplicationContainer.Resolve().PublishEvent(new ApplicationShutdownRequested()); } } } \ No newline at end of file diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj index 57c11430f..3f56ad5a6 100644 --- a/NzbDrone.Api/NzbDrone.Api.csproj +++ b/NzbDrone.Api/NzbDrone.Api.csproj @@ -85,6 +85,8 @@ + + diff --git a/NzbDrone.Api/NzbDroneApiModule.cs b/NzbDrone.Api/NzbDroneApiModule.cs index 9652387c6..aef3bca59 100644 --- a/NzbDrone.Api/NzbDroneApiModule.cs +++ b/NzbDrone.Api/NzbDroneApiModule.cs @@ -1,6 +1,4 @@ -using System.Linq; -using Nancy; -using Nancy.Responses; +using Nancy; namespace NzbDrone.Api { @@ -11,8 +9,5 @@ namespace NzbDrone.Api { Options["/"] = x => new Response(); } - - - } } \ No newline at end of file diff --git a/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs new file mode 100644 index 000000000..b82d79820 --- /dev/null +++ b/NzbDrone.Common.Test/EventingTests/MessageAggregatorCommandTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using NzbDrone.Common.Messaging; +using NzbDrone.Test.Common; + +namespace NzbDrone.Common.Test.EventingTests +{ + [TestFixture] + public class MessageAggregatorCommandTests : TestBase + { + [Test] + public void should_publish_command_to_executor() + { + var commandA = new CommandA(); + + var executor = new Mock>(); + var aggregator = new MessageAggregator(TestLogger, () => new List { executor.Object }); + aggregator.PublishCommand(commandA); + + executor.Verify(c => c.Execute(commandA), Times.Once()); + } + + + [Test] + public void should_throw_if_more_than_one_handler() + { + var commandA = new CommandA(); + + var executor1 = new Mock>(); + var executor2 = new Mock>(); + var aggregator = new MessageAggregator(TestLogger, () => new List { executor1.Object, executor2.Object }); + + Assert.Throws(() => aggregator.PublishCommand(commandA)); + } + + [Test] + public void should_not_publish_to_incompatible_executor() + { + var commandA = new CommandA(); + + var executor1 = new Mock>(); + var executor2 = new Mock>(); + var aggregator = new MessageAggregator(TestLogger, () => new List { executor1.Object, executor2.Object }); + + aggregator.PublishCommand(commandA); + + executor1.Verify(c => c.Execute(commandA), Times.Once()); + executor2.Verify(c => c.Execute(It.IsAny()), Times.Never()); + } + + [Test] + public void broken_executor_should_throw_the_exception() + { + var commandA = new CommandA(); + + var executor = new Mock>(); + + executor.Setup(c => c.Execute(It.IsAny())) + .Throws(new NotImplementedException()); + + var aggregator = new MessageAggregator(TestLogger, () => new List { executor.Object }); + Assert.Throws(() => aggregator.PublishCommand(commandA)); + } + } + + public class CommandA : ICommand + { + + } + + public class CommandB : ICommand + { + + } + +} \ No newline at end of file diff --git a/NzbDrone.Common.Test/EventingTests/EventAggregatorTests.cs b/NzbDrone.Common.Test/EventingTests/MessageAggregatorEventTests.cs similarity index 59% rename from NzbDrone.Common.Test/EventingTests/EventAggregatorTests.cs rename to NzbDrone.Common.Test/EventingTests/MessageAggregatorEventTests.cs index 0576d578c..e30d71339 100644 --- a/NzbDrone.Common.Test/EventingTests/EventAggregatorTests.cs +++ b/NzbDrone.Common.Test/EventingTests/MessageAggregatorEventTests.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; using Moq; using NUnit.Framework; using NzbDrone.Common.Messaging; @@ -8,17 +8,17 @@ using NzbDrone.Test.Common; namespace NzbDrone.Common.Test.EventingTests { [TestFixture] - public class ServiceNameFixture : TestBase + public class MessageAggregatorEventTests : TestBase { [Test] public void should_publish_event_to_handlers() { var eventA = new EventA(); - + var intHandler = new Mock>(); var aggregator = new MessageAggregator(TestLogger, () => new List { intHandler.Object }); - aggregator.Publish(eventA); + aggregator.PublishEvent(eventA); intHandler.Verify(c => c.Handle(eventA), Times.Once()); } @@ -31,7 +31,7 @@ namespace NzbDrone.Common.Test.EventingTests var intHandler1 = new Mock>(); var intHandler2 = new Mock>(); var aggregator = new MessageAggregator(TestLogger, () => new List { intHandler1.Object, intHandler2.Object }); - aggregator.Publish(eventA); + aggregator.PublishEvent(eventA); intHandler1.Verify(c => c.Handle(eventA), Times.Once()); intHandler2.Verify(c => c.Handle(eventA), Times.Once()); @@ -46,18 +46,41 @@ namespace NzbDrone.Common.Test.EventingTests var bHandler = new Mock>(); var aggregator = new MessageAggregator(TestLogger, () => new List { aHandler.Object, bHandler.Object }); - aggregator.Publish(eventA); + aggregator.PublishEvent(eventA); aHandler.Verify(c => c.Handle(eventA), Times.Once()); bHandler.Verify(c => c.Handle(It.IsAny()), Times.Never()); } + + [Test] + public void broken_handler_should_not_effect_others_handler() + { + var eventA = new EventA(); + + var intHandler1 = new Mock>(); + var intHandler2 = new Mock>(); + var intHandler3 = new Mock>(); + + intHandler2.Setup(c => c.Handle(It.IsAny())) + .Throws(new NotImplementedException()); + + var aggregator = new MessageAggregator(TestLogger, () => new List { intHandler1.Object, intHandler2.Object , intHandler3.Object}); + aggregator.PublishEvent(eventA); + + intHandler1.Verify(c => c.Handle(eventA), Times.Once()); + intHandler3.Verify(c => c.Handle(eventA), Times.Once()); + + + ExceptionVerification.ExpectedErrors(1); + } + } - public class EventA:IEvent + public class EventA : IEvent { - + } public class EventB : IEvent diff --git a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj index 2d9b65164..b42407546 100644 --- a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj +++ b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj @@ -79,7 +79,8 @@ - + + diff --git a/NzbDrone.Common/ContainerBuilderBase.cs b/NzbDrone.Common/ContainerBuilderBase.cs index fefb85333..e038665ee 100644 --- a/NzbDrone.Common/ContainerBuilderBase.cs +++ b/NzbDrone.Common/ContainerBuilderBase.cs @@ -51,6 +51,7 @@ namespace NzbDrone.Common if (implementations.Count == 1) { Container.Register(contractType, implementations.Single()).AsMultiInstance(); + Container.RegisterMultiple(contractType, implementations).AsMultiInstance(); } else { diff --git a/NzbDrone.Common/Messaging/IExecute.cs b/NzbDrone.Common/Messaging/IExecute.cs new file mode 100644 index 000000000..a065e0828 --- /dev/null +++ b/NzbDrone.Common/Messaging/IExecute.cs @@ -0,0 +1,7 @@ +namespace NzbDrone.Common.Messaging +{ + public interface IExecute : IProcessMessage where TCommand : ICommand + { + void Execute(TCommand message); + } +} \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/IHandle.cs b/NzbDrone.Common/Messaging/IHandle.cs index 39657dce9..ae40448d4 100644 --- a/NzbDrone.Common/Messaging/IHandle.cs +++ b/NzbDrone.Common/Messaging/IHandle.cs @@ -1,28 +1,12 @@ namespace NzbDrone.Common.Messaging { - /// - /// Denotes a class which can handle a particular type of message. - /// - /// The type of message to handle. - public interface IHandle : IProcessMessage where TEvent : IEvent + public interface IHandle : IProcessMessage where TEvent : IEvent { - /// - /// Handles the message synchronously. - /// - /// The message. void Handle(TEvent message); } - /// - /// Denotes a class which can handle a particular type of message. - /// - /// The type of message to handle. - public interface IHandleAsync : IProcessMessageAsync where TEvent : IEvent + public interface IHandleAsync : IProcessMessageAsync where TEvent : IEvent { - /// - /// Handles the message asynchronously. - /// - /// The message. void HandleAsync(TEvent message); } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/IMessageAggregator.cs b/NzbDrone.Common/Messaging/IMessageAggregator.cs index f16c5b4c1..0022b5be0 100644 --- a/NzbDrone.Common/Messaging/IMessageAggregator.cs +++ b/NzbDrone.Common/Messaging/IMessageAggregator.cs @@ -5,7 +5,7 @@ /// public interface IMessageAggregator { - void Publish(TEvent message) where TEvent : IEvent; - void Execute(TCommand message) where TCommand : ICommand; + void PublishEvent(TEvent @event) where TEvent : IEvent; + void PublishCommand(TCommand command) where TCommand : ICommand; } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/IProcessMessage.cs b/NzbDrone.Common/Messaging/IProcessMessage.cs index e39188c62..b008d9e9b 100644 --- a/NzbDrone.Common/Messaging/IProcessMessage.cs +++ b/NzbDrone.Common/Messaging/IProcessMessage.cs @@ -1,12 +1,11 @@ namespace NzbDrone.Common.Messaging { - /// - /// A marker interface for classes that subscribe to messages. - /// public interface IProcessMessage { } - /// - /// A marker interface for classes that subscribe to messages. - /// public interface IProcessMessageAsync : IProcessMessage { } + + + public interface IProcessMessage : IProcessMessage { } + + public interface IProcessMessageAsync : IProcessMessageAsync { } } \ No newline at end of file diff --git a/NzbDrone.Common/Messaging/MessageAggregator.cs b/NzbDrone.Common/Messaging/MessageAggregator.cs index cba7e6227..dd88ff283 100644 --- a/NzbDrone.Common/Messaging/MessageAggregator.cs +++ b/NzbDrone.Common/Messaging/MessageAggregator.cs @@ -17,33 +17,45 @@ namespace NzbDrone.Common.Messaging _handlers = handlers; } - public void Publish(TEvent message) where TEvent : IEvent + public void PublishEvent(TEvent @event) where TEvent : IEvent { - _logger.Trace("Publishing {0}", message.GetType().Name); + _logger.Trace("Publishing {0}", @event.GetType().Name); //call synchronous handlers first. foreach (var handler in _handlers().OfType>()) { - _logger.Debug("{0} -> {1}", message.GetType().Name, handler.GetType().Name); - handler.Handle(message); - _logger.Debug("{0} <- {1}", message.GetType().Name, handler.GetType().Name); + try + { + _logger.Debug("{0} -> {1}", @event.GetType().Name, handler.GetType().Name); + handler.Handle(@event); + _logger.Debug("{0} <- {1}", @event.GetType().Name, handler.GetType().Name); + } + catch (Exception e) + { + _logger.ErrorException(string.Format("{0} failed while processing [{1}]", handler.GetType().Name, @event.GetType().Name), e); + } } foreach (var handler in _handlers().OfType>()) { var handlerLocal = handler; Task.Factory.StartNew(() => - { - _logger.Debug("{0} ~> {1}", message.GetType().Name, handlerLocal.GetType().Name); - handlerLocal.HandleAsync(message); - _logger.Debug("{0} <~ {1}", message.GetType().Name, handlerLocal.GetType().Name); - }); + { + _logger.Debug("{0} ~> {1}", @event.GetType().Name, handlerLocal.GetType().Name); + handlerLocal.HandleAsync(@event); + _logger.Debug("{0} <~ {1}", @event.GetType().Name, handlerLocal.GetType().Name); + }); } } - public void Execute(TCommand message) where TCommand : ICommand + + public void PublishCommand(TCommand command) where TCommand : ICommand { - throw new NotImplementedException(); + _logger.Trace("Publishing {0}", command.GetType().Name); + var handler = _handlers().OfType>().Single(); + _logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name); + handler.Execute(command); + _logger.Debug("{0} <- {1}", command.GetType().Name, handler.GetType().Name); } } } diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index e9f268b8a..542afc695 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -105,6 +105,7 @@ + diff --git a/NzbDrone.Core/Download/DownloadService.cs b/NzbDrone.Core/Download/DownloadService.cs index 560e2d0d1..d08bb4906 100644 --- a/NzbDrone.Core/Download/DownloadService.cs +++ b/NzbDrone.Core/Download/DownloadService.cs @@ -50,7 +50,7 @@ namespace NzbDrone.Core.Download if (success) { _logger.Info("Report sent to download client. {0}", downloadTitle); - _messageAggregator.Publish(new EpisodeGrabbedEvent(episode)); + _messageAggregator.PublishEvent(new EpisodeGrabbedEvent(episode)); } return success; diff --git a/NzbDrone.Core/Indexers/RssSyncCommand.cs b/NzbDrone.Core/Indexers/RssSyncCommand.cs new file mode 100644 index 000000000..04a7a123b --- /dev/null +++ b/NzbDrone.Core/Indexers/RssSyncCommand.cs @@ -0,0 +1,9 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.Indexers +{ + public class RssSyncCommand : ICommand + { + + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Indexers/RssSyncService.cs b/NzbDrone.Core/Indexers/RssSyncService.cs index b1543c3a1..7edb96781 100644 --- a/NzbDrone.Core/Indexers/RssSyncService.cs +++ b/NzbDrone.Core/Indexers/RssSyncService.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using NLog; +using NzbDrone.Common.Messaging; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Download; @@ -11,7 +12,7 @@ namespace NzbDrone.Core.Indexers void Sync(); } - public class RssSyncService : IRssSyncService + public class RssSyncService : IRssSyncService, IExecute { private readonly IFetchAndParseRss _rssFetcherAndParser; private readonly IMakeDownloadDecision _downloadDecisionMaker; @@ -36,7 +37,7 @@ namespace NzbDrone.Core.Indexers //TODO: this will download multiple of same episode if they show up in RSS. need to //proposal: maybe get download decision one by one, that way - + var qualifiedReports = decisions .Where(c => c.Approved) .Select(c => c.Episode) @@ -60,5 +61,10 @@ namespace NzbDrone.Core.Indexers _logger.Info("RSS Sync Completed. Reports found: {0}, Fetches attempted: {1}", reports.Count, qualifiedReports.Count()); } + + public void Execute(RssSyncCommand message) + { + Sync(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Jobs/Implementations/RenameSeasonJob.cs b/NzbDrone.Core/Jobs/Implementations/RenameSeasonJob.cs index b7612161a..c4624f78d 100644 --- a/NzbDrone.Core/Jobs/Implementations/RenameSeasonJob.cs +++ b/NzbDrone.Core/Jobs/Implementations/RenameSeasonJob.cs @@ -90,7 +90,7 @@ namespace NzbDrone.Core.Jobs.Implementations } //Start AfterRename - _messageAggregator.Publish(new SeriesRenamedEvent(series)); + _messageAggregator.PublishEvent(new SeriesRenamedEvent(series)); notification.CurrentMessage = String.Format("Rename completed for {0} Season {1}", series.Title, options.SeasonNumber); } diff --git a/NzbDrone.Core/Jobs/Implementations/RenameSeriesJob.cs b/NzbDrone.Core/Jobs/Implementations/RenameSeriesJob.cs index 2543e51da..ca441fdca 100644 --- a/NzbDrone.Core/Jobs/Implementations/RenameSeriesJob.cs +++ b/NzbDrone.Core/Jobs/Implementations/RenameSeriesJob.cs @@ -89,7 +89,7 @@ namespace NzbDrone.Core.Jobs.Implementations //Start AfterRename - _messageAggregator.Publish(new SeriesRenamedEvent(series)); + _messageAggregator.PublishEvent(new SeriesRenamedEvent(series)); notification.CurrentMessage = String.Format("Rename completed for {0}", series.Title); } diff --git a/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs b/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs index 522ced33d..eacb01974 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs @@ -83,7 +83,7 @@ namespace NzbDrone.Core.MediaFiles if (newDownload) { - _messageAggregator.Publish(new EpisodeDownloadedEvent(parsedEpisodeInfo, series)); + _messageAggregator.PublishEvent(new EpisodeDownloadedEvent(parsedEpisodeInfo, series)); } return episodeFile; diff --git a/NzbDrone.Core/MediaFiles/MediaFileService.cs b/NzbDrone.Core/MediaFiles/MediaFileService.cs index 76d5168be..83a1693ae 100644 --- a/NzbDrone.Core/MediaFiles/MediaFileService.cs +++ b/NzbDrone.Core/MediaFiles/MediaFileService.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.MediaFiles public EpisodeFile Add(EpisodeFile episodeFile) { var addedFile = _mediaFileRepository.Insert(episodeFile); - _messageAggregator.Publish(new EpisodeFileAddedEvent(addedFile)); + _messageAggregator.PublishEvent(new EpisodeFileAddedEvent(addedFile)); return addedFile; } @@ -52,7 +52,7 @@ namespace NzbDrone.Core.MediaFiles public void Delete(EpisodeFile episodeFile) { _mediaFileRepository.Delete(episodeFile); - _messageAggregator.Publish(new EpisodeFileDeletedEvent(episodeFile)); + _messageAggregator.PublishEvent(new EpisodeFileDeletedEvent(episodeFile)); } public bool Exists(string path) diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 07efb651c..2f5a5f0ec 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -238,6 +238,7 @@ + diff --git a/NzbDrone.Core/Tv/EpisodeService.cs b/NzbDrone.Core/Tv/EpisodeService.cs index cd3f3e164..937eda0ef 100644 --- a/NzbDrone.Core/Tv/EpisodeService.cs +++ b/NzbDrone.Core/Tv/EpisodeService.cs @@ -211,12 +211,12 @@ namespace NzbDrone.Core.Tv if (newList.Any()) { - _messageAggregator.Publish(new EpisodeInfoAddedEvent(newList)); + _messageAggregator.PublishEvent(new EpisodeInfoAddedEvent(newList)); } if (updateList.Any()) { - _messageAggregator.Publish(new EpisodeInfoUpdatedEvent(updateList)); + _messageAggregator.PublishEvent(new EpisodeInfoUpdatedEvent(updateList)); } if (failCount != 0) diff --git a/NzbDrone.Core/Tv/SeriesService.cs b/NzbDrone.Core/Tv/SeriesService.cs index a19d92c13..cd1d780b5 100644 --- a/NzbDrone.Core/Tv/SeriesService.cs +++ b/NzbDrone.Core/Tv/SeriesService.cs @@ -83,7 +83,7 @@ namespace NzbDrone.Core.Tv //Todo: We need to get the UtcOffset from TVRage, since its not available from trakt - _messageAggregator.Publish(new SeriesUpdatedEvent(series)); + _messageAggregator.PublishEvent(new SeriesUpdatedEvent(series)); return series; } @@ -114,7 +114,7 @@ namespace NzbDrone.Core.Tv newSeries.BacklogSetting = BacklogSettingType.Inherit; _seriesRepository.Insert(newSeries); - _messageAggregator.Publish(new SeriesAddedEvent(newSeries)); + _messageAggregator.PublishEvent(new SeriesAddedEvent(newSeries)); return newSeries; } @@ -158,7 +158,7 @@ namespace NzbDrone.Core.Tv { var series = _seriesRepository.Get(seriesId); _seriesRepository.Delete(seriesId); - _messageAggregator.Publish(new SeriesDeletedEvent(series, deleteFiles)); + _messageAggregator.PublishEvent(new SeriesDeletedEvent(series, deleteFiles)); } public List GetAllSeries() diff --git a/NzbDrone.Integration.Test/CommandIntegerationTests.cs b/NzbDrone.Integration.Test/CommandIntegerationTests.cs new file mode 100644 index 000000000..7899393d8 --- /dev/null +++ b/NzbDrone.Integration.Test/CommandIntegerationTests.cs @@ -0,0 +1,17 @@ +using NUnit.Framework; +using NzbDrone.Api.Commands; + +namespace NzbDrone.Integration.Test +{ + [TestFixture] + public class CommandIntegrationTest : IntegrationTest + { + [Test] + public void should_be_able_to_run_rss_sync() + { + Commands.Post(new CommandResource {Command = "rsssync"}); + } + + + } +} \ No newline at end of file diff --git a/NzbDrone.Integration.Test/IntegrationTest.cs b/NzbDrone.Integration.Test/IntegrationTest.cs index e94fc1032..5359ef15f 100644 --- a/NzbDrone.Integration.Test/IntegrationTest.cs +++ b/NzbDrone.Integration.Test/IntegrationTest.cs @@ -6,6 +6,7 @@ using NLog.Targets; using NUnit.Framework; using Nancy.Hosting.Self; using NzbDrone.Api; +using NzbDrone.Api.Commands; using NzbDrone.Api.RootFolders; using NzbDrone.Common; using NzbDrone.Core.Datastore; @@ -29,6 +30,7 @@ namespace NzbDrone.Integration.Test protected SeriesClient Series; protected ClientBase RootFolders; + protected ClientBase Commands; static IntegrationTest() { @@ -84,6 +86,7 @@ namespace NzbDrone.Integration.Test RestClient = new RestClient(url + "/api/"); Series = new SeriesClient(RestClient); RootFolders = new ClientBase(RestClient); + Commands = new ClientBase(RestClient); _host.Start(); } @@ -96,4 +99,5 @@ namespace NzbDrone.Integration.Test _bootstrapper.Shutdown(); } } + } diff --git a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index f5128bca0..983820739 100644 --- a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -76,6 +76,7 @@ + diff --git a/NzbDrone.Test.Common/TestBase.cs b/NzbDrone.Test.Common/TestBase.cs index 9f4e90af2..6d161abf5 100644 --- a/NzbDrone.Test.Common/TestBase.cs +++ b/NzbDrone.Test.Common/TestBase.cs @@ -122,12 +122,12 @@ namespace NzbDrone.Test.Common protected void VerifyEventPublished(Times times) where TEvent : IEvent { - Mocker.GetMock().Verify(c => c.Publish(It.IsAny()), times); + Mocker.GetMock().Verify(c => c.PublishEvent(It.IsAny()), times); } protected void VerifyEventNotPublished() where TEvent : IEvent { - Mocker.GetMock().Verify(c => c.Publish(It.IsAny()), Times.Never()); + Mocker.GetMock().Verify(c => c.PublishEvent(It.IsAny()), Times.Never()); } } } diff --git a/package.json b/package.json index d470f61e7..ec5024b1c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "grunt-contrib-concat": "*", "grunt-contrib-copy": "*", "grunt-wrap": "*", - "grunt-curl": "~0.6.0", + "grunt-curl": "*", "grunt-notify": "*" } }