added commands.
they can be triggered using the api api/command/
This commit is contained in:
parent
68ee71ea81
commit
182192e0ba
|
@ -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<CommandResource>
|
||||||
|
{
|
||||||
|
private readonly IMessageAggregator _messageAggregator;
|
||||||
|
private readonly IEnumerable<ICommand> _commands;
|
||||||
|
|
||||||
|
public CommandModule(IMessageAggregator messageAggregator, IEnumerable<ICommand> 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<ICommand>(commandType);
|
||||||
|
var method = typeof(IMessageAggregator).GetMethod("PublishCommand");
|
||||||
|
var genericMethod = method.MakeGenericMethod(commandType);
|
||||||
|
genericMethod.Invoke(_messageAggregator, new[] { command });
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Commands
|
||||||
|
{
|
||||||
|
public class CommandResource : RestResource
|
||||||
|
{
|
||||||
|
public string Command { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System.IO;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using Nancy.Responses;
|
using Nancy.Responses;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
|
@ -11,11 +12,16 @@ namespace NzbDrone.Api.Extensions
|
||||||
private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer(Serializer);
|
private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer(Serializer);
|
||||||
|
|
||||||
public static T FromJson<T>(this Stream body) where T : class, new()
|
public static T FromJson<T>(this Stream body) where T : class, new()
|
||||||
|
{
|
||||||
|
return FromJson<T>(body, typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T FromJson<T>(this Stream body, Type type)
|
||||||
{
|
{
|
||||||
var reader = new StreamReader(body, true);
|
var reader = new StreamReader(body, true);
|
||||||
body.Position = 0;
|
body.Position = 0;
|
||||||
var value = reader.ReadToEnd();
|
var value = reader.ReadToEnd();
|
||||||
return Serializer.Deserialize<T>(value);
|
return (T)Serializer.Deserialize(value, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsonResponse<TModel> AsResponse<TModel>(this TModel model, HttpStatusCode statusCode = HttpStatusCode.OK)
|
public static JsonResponse<TModel> AsResponse<TModel>(this TModel model, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace NzbDrone.Api
|
||||||
AutomapperBootstraper.InitializeAutomapper();
|
AutomapperBootstraper.InitializeAutomapper();
|
||||||
RegisterReporting(container);
|
RegisterReporting(container);
|
||||||
|
|
||||||
container.Resolve<IMessageAggregator>().Publish(new ApplicationStartedEvent());
|
container.Resolve<IMessageAggregator>().PublishEvent(new ApplicationStartedEvent());
|
||||||
|
|
||||||
ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve<ErrorPipeline>().HandleException);
|
ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve<ErrorPipeline>().HandleException);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ namespace NzbDrone.Api
|
||||||
|
|
||||||
public void Shutdown()
|
public void Shutdown()
|
||||||
{
|
{
|
||||||
ApplicationContainer.Resolve<IMessageAggregator>().Publish(new ApplicationShutdownRequested());
|
ApplicationContainer.Resolve<IMessageAggregator>().PublishEvent(new ApplicationShutdownRequested());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -85,6 +85,8 @@
|
||||||
<Compile Include="AutomapperBootstraper.cs" />
|
<Compile Include="AutomapperBootstraper.cs" />
|
||||||
<Compile Include="Calendar\CalendarModule.cs" />
|
<Compile Include="Calendar\CalendarModule.cs" />
|
||||||
<Compile Include="Calendar\CalendarResource.cs" />
|
<Compile Include="Calendar\CalendarResource.cs" />
|
||||||
|
<Compile Include="Commands\CommandModule.cs" />
|
||||||
|
<Compile Include="Commands\CommandResource.cs" />
|
||||||
<Compile Include="Directories\DirectoryModule.cs" />
|
<Compile Include="Directories\DirectoryModule.cs" />
|
||||||
<Compile Include="Episodes\EpisodeModule.cs" />
|
<Compile Include="Episodes\EpisodeModule.cs" />
|
||||||
<Compile Include="Episodes\EpisodeResource.cs" />
|
<Compile Include="Episodes\EpisodeResource.cs" />
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using System.Linq;
|
using Nancy;
|
||||||
using Nancy;
|
|
||||||
using Nancy.Responses;
|
|
||||||
|
|
||||||
namespace NzbDrone.Api
|
namespace NzbDrone.Api
|
||||||
{
|
{
|
||||||
|
@ -11,8 +9,5 @@ namespace NzbDrone.Api
|
||||||
{
|
{
|
||||||
Options["/"] = x => new Response();
|
Options["/"] = x => new Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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<IExecute<CommandA>>();
|
||||||
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { 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<IExecute<CommandA>>();
|
||||||
|
var executor2 = new Mock<IExecute<CommandA>>();
|
||||||
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { executor1.Object, executor2.Object });
|
||||||
|
|
||||||
|
Assert.Throws<InvalidOperationException>(() => aggregator.PublishCommand(commandA));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_publish_to_incompatible_executor()
|
||||||
|
{
|
||||||
|
var commandA = new CommandA();
|
||||||
|
|
||||||
|
var executor1 = new Mock<IExecute<CommandA>>();
|
||||||
|
var executor2 = new Mock<IExecute<CommandB>>();
|
||||||
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { executor1.Object, executor2.Object });
|
||||||
|
|
||||||
|
aggregator.PublishCommand(commandA);
|
||||||
|
|
||||||
|
executor1.Verify(c => c.Execute(commandA), Times.Once());
|
||||||
|
executor2.Verify(c => c.Execute(It.IsAny<CommandB>()), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void broken_executor_should_throw_the_exception()
|
||||||
|
{
|
||||||
|
var commandA = new CommandA();
|
||||||
|
|
||||||
|
var executor = new Mock<IExecute<CommandA>>();
|
||||||
|
|
||||||
|
executor.Setup(c => c.Execute(It.IsAny<CommandA>()))
|
||||||
|
.Throws(new NotImplementedException());
|
||||||
|
|
||||||
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { executor.Object });
|
||||||
|
Assert.Throws<NotImplementedException>(() => aggregator.PublishCommand(commandA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandA : ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandB : ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Linq;
|
using System.Collections.Generic;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
@ -8,7 +8,7 @@ using NzbDrone.Test.Common;
|
||||||
namespace NzbDrone.Common.Test.EventingTests
|
namespace NzbDrone.Common.Test.EventingTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class ServiceNameFixture : TestBase
|
public class MessageAggregatorEventTests : TestBase
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void should_publish_event_to_handlers()
|
public void should_publish_event_to_handlers()
|
||||||
|
@ -18,7 +18,7 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
|
|
||||||
var intHandler = new Mock<IHandle<EventA>>();
|
var intHandler = new Mock<IHandle<EventA>>();
|
||||||
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { intHandler.Object });
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { intHandler.Object });
|
||||||
aggregator.Publish(eventA);
|
aggregator.PublishEvent(eventA);
|
||||||
|
|
||||||
intHandler.Verify(c => c.Handle(eventA), Times.Once());
|
intHandler.Verify(c => c.Handle(eventA), Times.Once());
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
var intHandler1 = new Mock<IHandle<EventA>>();
|
var intHandler1 = new Mock<IHandle<EventA>>();
|
||||||
var intHandler2 = new Mock<IHandle<EventA>>();
|
var intHandler2 = new Mock<IHandle<EventA>>();
|
||||||
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { intHandler1.Object, intHandler2.Object });
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { intHandler1.Object, intHandler2.Object });
|
||||||
aggregator.Publish(eventA);
|
aggregator.PublishEvent(eventA);
|
||||||
|
|
||||||
intHandler1.Verify(c => c.Handle(eventA), Times.Once());
|
intHandler1.Verify(c => c.Handle(eventA), Times.Once());
|
||||||
intHandler2.Verify(c => c.Handle(eventA), Times.Once());
|
intHandler2.Verify(c => c.Handle(eventA), Times.Once());
|
||||||
|
@ -46,12 +46,35 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
var bHandler = new Mock<IHandle<EventB>>();
|
var bHandler = new Mock<IHandle<EventB>>();
|
||||||
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { aHandler.Object, bHandler.Object });
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { aHandler.Object, bHandler.Object });
|
||||||
|
|
||||||
aggregator.Publish(eventA);
|
aggregator.PublishEvent(eventA);
|
||||||
|
|
||||||
aHandler.Verify(c => c.Handle(eventA), Times.Once());
|
aHandler.Verify(c => c.Handle(eventA), Times.Once());
|
||||||
bHandler.Verify(c => c.Handle(It.IsAny<EventB>()), Times.Never());
|
bHandler.Verify(c => c.Handle(It.IsAny<EventB>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void broken_handler_should_not_effect_others_handler()
|
||||||
|
{
|
||||||
|
var eventA = new EventA();
|
||||||
|
|
||||||
|
var intHandler1 = new Mock<IHandle<EventA>>();
|
||||||
|
var intHandler2 = new Mock<IHandle<EventA>>();
|
||||||
|
var intHandler3 = new Mock<IHandle<EventA>>();
|
||||||
|
|
||||||
|
intHandler2.Setup(c => c.Handle(It.IsAny<EventA>()))
|
||||||
|
.Throws(new NotImplementedException());
|
||||||
|
|
||||||
|
var aggregator = new MessageAggregator(TestLogger, () => new List<IProcessMessage> { 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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,8 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ConfigFileProviderTest.cs" />
|
<Compile Include="ConfigFileProviderTest.cs" />
|
||||||
<Compile Include="EventingTests\EventAggregatorTests.cs" />
|
<Compile Include="EventingTests\MessageAggregatorCommandTests.cs" />
|
||||||
|
<Compile Include="EventingTests\MessageAggregatorEventTests.cs" />
|
||||||
<Compile Include="ReflectionExtensions.cs" />
|
<Compile Include="ReflectionExtensions.cs" />
|
||||||
<Compile Include="ReportingService_ReportParseError_Fixture.cs" />
|
<Compile Include="ReportingService_ReportParseError_Fixture.cs" />
|
||||||
<Compile Include="PathExtentionFixture.cs" />
|
<Compile Include="PathExtentionFixture.cs" />
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace NzbDrone.Common
|
||||||
if (implementations.Count == 1)
|
if (implementations.Count == 1)
|
||||||
{
|
{
|
||||||
Container.Register(contractType, implementations.Single()).AsMultiInstance();
|
Container.Register(contractType, implementations.Single()).AsMultiInstance();
|
||||||
|
Container.RegisterMultiple(contractType, implementations).AsMultiInstance();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace NzbDrone.Common.Messaging
|
||||||
|
{
|
||||||
|
public interface IExecute<TCommand> : IProcessMessage<TCommand> where TCommand : ICommand
|
||||||
|
{
|
||||||
|
void Execute(TCommand message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,12 @@
|
||||||
namespace NzbDrone.Common.Messaging
|
namespace NzbDrone.Common.Messaging
|
||||||
{
|
{
|
||||||
/// <summary>
|
public interface IHandle<TEvent> : IProcessMessage<TEvent> where TEvent : IEvent
|
||||||
/// Denotes a class which can handle a particular type of message.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name = "TEvent">The type of message to handle.</typeparam>
|
|
||||||
public interface IHandle<TEvent> : IProcessMessage where TEvent : IEvent
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Handles the message synchronously.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name = "message">The message.</param>
|
|
||||||
void Handle(TEvent message);
|
void Handle(TEvent message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public interface IHandleAsync<TEvent> : IProcessMessageAsync<TEvent> where TEvent : IEvent
|
||||||
/// Denotes a class which can handle a particular type of message.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name = "TEvent">The type of message to handle.</typeparam>
|
|
||||||
public interface IHandleAsync<TEvent> : IProcessMessageAsync where TEvent : IEvent
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Handles the message asynchronously.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name = "message">The message.</param>
|
|
||||||
void HandleAsync(TEvent message);
|
void HandleAsync(TEvent message);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMessageAggregator
|
public interface IMessageAggregator
|
||||||
{
|
{
|
||||||
void Publish<TEvent>(TEvent message) where TEvent : IEvent;
|
void PublishEvent<TEvent>(TEvent @event) where TEvent : IEvent;
|
||||||
void Execute<TCommand>(TCommand message) where TCommand : ICommand;
|
void PublishCommand<TCommand>(TCommand command) where TCommand : ICommand;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
namespace NzbDrone.Common.Messaging
|
namespace NzbDrone.Common.Messaging
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// A marker interface for classes that subscribe to messages.
|
|
||||||
/// </summary>
|
|
||||||
public interface IProcessMessage { }
|
public interface IProcessMessage { }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A marker interface for classes that subscribe to messages.
|
|
||||||
/// </summary>
|
|
||||||
public interface IProcessMessageAsync : IProcessMessage { }
|
public interface IProcessMessageAsync : IProcessMessage { }
|
||||||
|
|
||||||
|
|
||||||
|
public interface IProcessMessage<TMessage> : IProcessMessage { }
|
||||||
|
|
||||||
|
public interface IProcessMessageAsync<TMessage> : IProcessMessageAsync { }
|
||||||
}
|
}
|
|
@ -17,16 +17,23 @@ namespace NzbDrone.Common.Messaging
|
||||||
_handlers = handlers;
|
_handlers = handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Publish<TEvent>(TEvent message) where TEvent : IEvent
|
public void PublishEvent<TEvent>(TEvent @event) where TEvent : IEvent
|
||||||
{
|
{
|
||||||
_logger.Trace("Publishing {0}", message.GetType().Name);
|
_logger.Trace("Publishing {0}", @event.GetType().Name);
|
||||||
|
|
||||||
//call synchronous handlers first.
|
//call synchronous handlers first.
|
||||||
foreach (var handler in _handlers().OfType<IHandle<TEvent>>())
|
foreach (var handler in _handlers().OfType<IHandle<TEvent>>())
|
||||||
{
|
{
|
||||||
_logger.Debug("{0} -> {1}", message.GetType().Name, handler.GetType().Name);
|
try
|
||||||
handler.Handle(message);
|
{
|
||||||
_logger.Debug("{0} <- {1}", message.GetType().Name, handler.GetType().Name);
|
_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<IHandleAsync<TEvent>>())
|
foreach (var handler in _handlers().OfType<IHandleAsync<TEvent>>())
|
||||||
|
@ -34,16 +41,21 @@ namespace NzbDrone.Common.Messaging
|
||||||
var handlerLocal = handler;
|
var handlerLocal = handler;
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
_logger.Debug("{0} ~> {1}", message.GetType().Name, handlerLocal.GetType().Name);
|
_logger.Debug("{0} ~> {1}", @event.GetType().Name, handlerLocal.GetType().Name);
|
||||||
handlerLocal.HandleAsync(message);
|
handlerLocal.HandleAsync(@event);
|
||||||
_logger.Debug("{0} <~ {1}", message.GetType().Name, handlerLocal.GetType().Name);
|
_logger.Debug("{0} <~ {1}", @event.GetType().Name, handlerLocal.GetType().Name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute<TCommand>(TCommand message) where TCommand : ICommand
|
|
||||||
|
public void PublishCommand<TCommand>(TCommand command) where TCommand : ICommand
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_logger.Trace("Publishing {0}", command.GetType().Name);
|
||||||
|
var handler = _handlers().OfType<IExecute<TCommand>>().Single();
|
||||||
|
_logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name);
|
||||||
|
handler.Execute(command);
|
||||||
|
_logger.Debug("{0} <- {1}", command.GetType().Name, handler.GetType().Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
<Compile Include="EnsureThat\Resources\ExceptionMessages.Designer.cs" />
|
<Compile Include="EnsureThat\Resources\ExceptionMessages.Designer.cs" />
|
||||||
<Compile Include="EnsureThat\StringExtensions.cs" />
|
<Compile Include="EnsureThat\StringExtensions.cs" />
|
||||||
<Compile Include="EnsureThat\TypeParam.cs" />
|
<Compile Include="EnsureThat\TypeParam.cs" />
|
||||||
|
<Compile Include="Messaging\IExecute.cs" />
|
||||||
<Compile Include="Messaging\ICommand.cs" />
|
<Compile Include="Messaging\ICommand.cs" />
|
||||||
<Compile Include="Messaging\IMessage.cs" />
|
<Compile Include="Messaging\IMessage.cs" />
|
||||||
<Compile Include="Messaging\IProcessMessage.cs" />
|
<Compile Include="Messaging\IProcessMessage.cs" />
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace NzbDrone.Core.Download
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
_logger.Info("Report sent to download client. {0}", downloadTitle);
|
_logger.Info("Report sent to download client. {0}", downloadTitle);
|
||||||
_messageAggregator.Publish(new EpisodeGrabbedEvent(episode));
|
_messageAggregator.PublishEvent(new EpisodeGrabbedEvent(episode));
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Indexers
|
||||||
|
{
|
||||||
|
public class RssSyncCommand : ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@ namespace NzbDrone.Core.Indexers
|
||||||
void Sync();
|
void Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RssSyncService : IRssSyncService
|
public class RssSyncService : IRssSyncService, IExecute<RssSyncCommand>
|
||||||
{
|
{
|
||||||
private readonly IFetchAndParseRss _rssFetcherAndParser;
|
private readonly IFetchAndParseRss _rssFetcherAndParser;
|
||||||
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
||||||
|
@ -60,5 +61,10 @@ namespace NzbDrone.Core.Indexers
|
||||||
|
|
||||||
_logger.Info("RSS Sync Completed. Reports found: {0}, Fetches attempted: {1}", reports.Count, qualifiedReports.Count());
|
_logger.Info("RSS Sync Completed. Reports found: {0}, Fetches attempted: {1}", reports.Count, qualifiedReports.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Execute(RssSyncCommand message)
|
||||||
|
{
|
||||||
|
Sync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -90,7 +90,7 @@ namespace NzbDrone.Core.Jobs.Implementations
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start AfterRename
|
//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);
|
notification.CurrentMessage = String.Format("Rename completed for {0} Season {1}", series.Title, options.SeasonNumber);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace NzbDrone.Core.Jobs.Implementations
|
||||||
|
|
||||||
//Start AfterRename
|
//Start AfterRename
|
||||||
|
|
||||||
_messageAggregator.Publish(new SeriesRenamedEvent(series));
|
_messageAggregator.PublishEvent(new SeriesRenamedEvent(series));
|
||||||
|
|
||||||
notification.CurrentMessage = String.Format("Rename completed for {0}", series.Title);
|
notification.CurrentMessage = String.Format("Rename completed for {0}", series.Title);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
||||||
if (newDownload)
|
if (newDownload)
|
||||||
{
|
{
|
||||||
_messageAggregator.Publish(new EpisodeDownloadedEvent(parsedEpisodeInfo, series));
|
_messageAggregator.PublishEvent(new EpisodeDownloadedEvent(parsedEpisodeInfo, series));
|
||||||
}
|
}
|
||||||
|
|
||||||
return episodeFile;
|
return episodeFile;
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
public EpisodeFile Add(EpisodeFile episodeFile)
|
public EpisodeFile Add(EpisodeFile episodeFile)
|
||||||
{
|
{
|
||||||
var addedFile = _mediaFileRepository.Insert(episodeFile);
|
var addedFile = _mediaFileRepository.Insert(episodeFile);
|
||||||
_messageAggregator.Publish(new EpisodeFileAddedEvent(addedFile));
|
_messageAggregator.PublishEvent(new EpisodeFileAddedEvent(addedFile));
|
||||||
return addedFile;
|
return addedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
public void Delete(EpisodeFile episodeFile)
|
public void Delete(EpisodeFile episodeFile)
|
||||||
{
|
{
|
||||||
_mediaFileRepository.Delete(episodeFile);
|
_mediaFileRepository.Delete(episodeFile);
|
||||||
_messageAggregator.Publish(new EpisodeFileDeletedEvent(episodeFile));
|
_messageAggregator.PublishEvent(new EpisodeFileDeletedEvent(episodeFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Exists(string path)
|
public bool Exists(string path)
|
||||||
|
|
|
@ -238,6 +238,7 @@
|
||||||
<Compile Include="Indexers\IIndexerBase.cs" />
|
<Compile Include="Indexers\IIndexerBase.cs" />
|
||||||
<Compile Include="Indexers\IndexerSettingUpdatedEvent.cs" />
|
<Compile Include="Indexers\IndexerSettingUpdatedEvent.cs" />
|
||||||
<Compile Include="Indexers\IndexerWithSetting.cs" />
|
<Compile Include="Indexers\IndexerWithSetting.cs" />
|
||||||
|
<Compile Include="Indexers\RssSyncCommand.cs" />
|
||||||
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
|
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
|
||||||
<Compile Include="MediaFiles\Events\EpisodeDownloadedEvent.cs" />
|
<Compile Include="MediaFiles\Events\EpisodeDownloadedEvent.cs" />
|
||||||
<Compile Include="Download\EpisodeGrabbedEvent.cs" />
|
<Compile Include="Download\EpisodeGrabbedEvent.cs" />
|
||||||
|
|
|
@ -211,12 +211,12 @@ namespace NzbDrone.Core.Tv
|
||||||
|
|
||||||
if (newList.Any())
|
if (newList.Any())
|
||||||
{
|
{
|
||||||
_messageAggregator.Publish(new EpisodeInfoAddedEvent(newList));
|
_messageAggregator.PublishEvent(new EpisodeInfoAddedEvent(newList));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateList.Any())
|
if (updateList.Any())
|
||||||
{
|
{
|
||||||
_messageAggregator.Publish(new EpisodeInfoUpdatedEvent(updateList));
|
_messageAggregator.PublishEvent(new EpisodeInfoUpdatedEvent(updateList));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failCount != 0)
|
if (failCount != 0)
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace NzbDrone.Core.Tv
|
||||||
|
|
||||||
//Todo: We need to get the UtcOffset from TVRage, since its not available from trakt
|
//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;
|
return series;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ namespace NzbDrone.Core.Tv
|
||||||
newSeries.BacklogSetting = BacklogSettingType.Inherit;
|
newSeries.BacklogSetting = BacklogSettingType.Inherit;
|
||||||
|
|
||||||
_seriesRepository.Insert(newSeries);
|
_seriesRepository.Insert(newSeries);
|
||||||
_messageAggregator.Publish(new SeriesAddedEvent(newSeries));
|
_messageAggregator.PublishEvent(new SeriesAddedEvent(newSeries));
|
||||||
|
|
||||||
return newSeries;
|
return newSeries;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ namespace NzbDrone.Core.Tv
|
||||||
{
|
{
|
||||||
var series = _seriesRepository.Get(seriesId);
|
var series = _seriesRepository.Get(seriesId);
|
||||||
_seriesRepository.Delete(seriesId);
|
_seriesRepository.Delete(seriesId);
|
||||||
_messageAggregator.Publish(new SeriesDeletedEvent(series, deleteFiles));
|
_messageAggregator.PublishEvent(new SeriesDeletedEvent(series, deleteFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Series> GetAllSeries()
|
public List<Series> GetAllSeries()
|
||||||
|
|
|
@ -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"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ using NLog.Targets;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Nancy.Hosting.Self;
|
using Nancy.Hosting.Self;
|
||||||
using NzbDrone.Api;
|
using NzbDrone.Api;
|
||||||
|
using NzbDrone.Api.Commands;
|
||||||
using NzbDrone.Api.RootFolders;
|
using NzbDrone.Api.RootFolders;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
@ -29,6 +30,7 @@ namespace NzbDrone.Integration.Test
|
||||||
|
|
||||||
protected SeriesClient Series;
|
protected SeriesClient Series;
|
||||||
protected ClientBase<RootFolderResource> RootFolders;
|
protected ClientBase<RootFolderResource> RootFolders;
|
||||||
|
protected ClientBase<CommandResource> Commands;
|
||||||
|
|
||||||
static IntegrationTest()
|
static IntegrationTest()
|
||||||
{
|
{
|
||||||
|
@ -84,6 +86,7 @@ namespace NzbDrone.Integration.Test
|
||||||
RestClient = new RestClient(url + "/api/");
|
RestClient = new RestClient(url + "/api/");
|
||||||
Series = new SeriesClient(RestClient);
|
Series = new SeriesClient(RestClient);
|
||||||
RootFolders = new ClientBase<RootFolderResource>(RestClient);
|
RootFolders = new ClientBase<RootFolderResource>(RestClient);
|
||||||
|
Commands = new ClientBase<CommandResource>(RestClient);
|
||||||
|
|
||||||
_host.Start();
|
_host.Start();
|
||||||
}
|
}
|
||||||
|
@ -96,4 +99,5 @@ namespace NzbDrone.Integration.Test
|
||||||
_bootstrapper.Shutdown();
|
_bootstrapper.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Client\ClientBase.cs" />
|
<Compile Include="Client\ClientBase.cs" />
|
||||||
<Compile Include="Client\SeriesClient.cs" />
|
<Compile Include="Client\SeriesClient.cs" />
|
||||||
|
<Compile Include="CommandIntegerationTests.cs" />
|
||||||
<Compile Include="IntegrationTest.cs" />
|
<Compile Include="IntegrationTest.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="RootFolderIntegrationTest.cs" />
|
<Compile Include="RootFolderIntegrationTest.cs" />
|
||||||
|
|
|
@ -122,12 +122,12 @@ namespace NzbDrone.Test.Common
|
||||||
|
|
||||||
protected void VerifyEventPublished<TEvent>(Times times) where TEvent : IEvent
|
protected void VerifyEventPublished<TEvent>(Times times) where TEvent : IEvent
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IMessageAggregator>().Verify(c => c.Publish(It.IsAny<TEvent>()), times);
|
Mocker.GetMock<IMessageAggregator>().Verify(c => c.PublishEvent(It.IsAny<TEvent>()), times);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void VerifyEventNotPublished<TEvent>() where TEvent : IEvent
|
protected void VerifyEventNotPublished<TEvent>() where TEvent : IEvent
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IMessageAggregator>().Verify(c => c.Publish(It.IsAny<TEvent>()), Times.Never());
|
Mocker.GetMock<IMessageAggregator>().Verify(c => c.PublishEvent(It.IsAny<TEvent>()), Times.Never());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
"grunt-contrib-concat": "*",
|
"grunt-contrib-concat": "*",
|
||||||
"grunt-contrib-copy": "*",
|
"grunt-contrib-copy": "*",
|
||||||
"grunt-wrap": "*",
|
"grunt-wrap": "*",
|
||||||
"grunt-curl": "~0.6.0",
|
"grunt-curl": "*",
|
||||||
"grunt-notify": "*"
|
"grunt-notify": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue