Merge branch 'ui-notifications' into develop
Conflicts: NzbDrone.Common/NzbDrone.Common.csproj UI/Series/Details/SeasonLayout.js
This commit is contained in:
commit
a7eb331d4e
|
@ -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<CommandStartedEvent>,
|
||||||
|
IHandleAsync<CommandCompletedEvent>,
|
||||||
|
IHandleAsync<CommandFailedEvent>
|
||||||
|
{
|
||||||
|
public override string Resource
|
||||||
|
{
|
||||||
|
get { return "/Command"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleAsync(CommandStartedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastMessage(message.TrackedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleAsync(CommandCompletedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastMessage(message.TrackedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleAsync(CommandFailedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastMessage(message.TrackedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BroadcastMessage(TrackedCommand trackedCommand)
|
||||||
|
{
|
||||||
|
var context = ((ConnectionManager)GlobalHost.ConnectionManager).GetConnection(GetType());
|
||||||
|
context.Connection.Broadcast(trackedCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,10 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Api.Mapping;
|
||||||
using NzbDrone.Common.Composition;
|
using NzbDrone.Common.Composition;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Commands
|
namespace NzbDrone.Api.Commands
|
||||||
{
|
{
|
||||||
|
@ -11,14 +13,16 @@ namespace NzbDrone.Api.Commands
|
||||||
{
|
{
|
||||||
private readonly IMessageAggregator _messageAggregator;
|
private readonly IMessageAggregator _messageAggregator;
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
|
private readonly ITrackCommands _trackCommands;
|
||||||
|
|
||||||
public CommandModule(IMessageAggregator messageAggregator, IContainer container)
|
public CommandModule(IMessageAggregator messageAggregator, IContainer container, ITrackCommands trackCommands)
|
||||||
{
|
{
|
||||||
_messageAggregator = messageAggregator;
|
_messageAggregator = messageAggregator;
|
||||||
_container = container;
|
_container = container;
|
||||||
|
_trackCommands = trackCommands;
|
||||||
|
|
||||||
Post["/"] = x => RunCommand(ReadResourceFromRequest());
|
Post["/"] = x => RunCommand(ReadResourceFromRequest());
|
||||||
|
Get["/"] = x => GetAllCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response RunCommand(CommandResource resource)
|
private Response RunCommand(CommandResource resource)
|
||||||
|
@ -29,9 +33,15 @@ namespace NzbDrone.Api.Commands
|
||||||
.Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase));
|
.Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
dynamic command = Request.Body.FromJson(commandType);
|
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()
|
||||||
|
{
|
||||||
|
return _trackCommands.AllTracked().AsResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,6 @@ namespace NzbDrone.Api.Extensions
|
||||||
{
|
{
|
||||||
private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer();
|
private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer();
|
||||||
|
|
||||||
|
|
||||||
public static readonly string LastModified = BuildInfo.BuildDateTime.ToString("r");
|
public static readonly string LastModified = BuildInfo.BuildDateTime.ToString("r");
|
||||||
|
|
||||||
public static T FromJson<T>(this Stream body) where T : class, new()
|
public static T FromJson<T>(this Stream body) where T : class, new()
|
||||||
|
@ -25,7 +24,6 @@ namespace NzbDrone.Api.Extensions
|
||||||
return (T)FromJson(body, type);
|
return (T)FromJson(body, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static object FromJson(this Stream body, Type type)
|
public static object FromJson(this Stream body, Type type)
|
||||||
{
|
{
|
||||||
var reader = new StreamReader(body, true);
|
var reader = new StreamReader(body, true);
|
||||||
|
|
|
@ -10,6 +10,7 @@ using NzbDrone.Common.Instrumentation;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.Instrumentation;
|
using NzbDrone.Core.Instrumentation;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
|
using NzbDrone.Core.ProgressMessaging;
|
||||||
using TinyIoC;
|
using TinyIoC;
|
||||||
|
|
||||||
namespace NzbDrone.Api
|
namespace NzbDrone.Api
|
||||||
|
@ -29,14 +30,12 @@ namespace NzbDrone.Api
|
||||||
{
|
{
|
||||||
_logger.Info("Starting NzbDrone API");
|
_logger.Info("Starting NzbDrone API");
|
||||||
|
|
||||||
|
|
||||||
RegisterPipelines(pipelines);
|
RegisterPipelines(pipelines);
|
||||||
|
|
||||||
container.Resolve<DatabaseTarget>().Register();
|
container.Resolve<DatabaseTarget>().Register();
|
||||||
container.Resolve<IEnableBasicAuthInNancy>().Register(pipelines);
|
container.Resolve<IEnableBasicAuthInNancy>().Register(pipelines);
|
||||||
container.Resolve<IMessageAggregator>().PublishEvent(new ApplicationStartedEvent());
|
container.Resolve<IMessageAggregator>().PublishEvent(new ApplicationStartedEvent());
|
||||||
|
|
||||||
|
|
||||||
ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve<NzbDroneErrorPipeline>().HandleException);
|
ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve<NzbDroneErrorPipeline>().HandleException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +47,8 @@ namespace NzbDrone.Api
|
||||||
{
|
{
|
||||||
registerNancyPipeline.Register(pipelines);
|
registerNancyPipeline.Register(pipelines);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override TinyIoCContainer GetApplicationContainer()
|
protected override TinyIoCContainer GetApplicationContainer()
|
||||||
{
|
{
|
||||||
return _tinyIoCContainer;
|
return _tinyIoCContainer;
|
||||||
|
|
|
@ -83,8 +83,12 @@
|
||||||
<Compile Include="ClientSchema\SelectOption.cs" />
|
<Compile Include="ClientSchema\SelectOption.cs" />
|
||||||
<Compile Include="Commands\CommandModule.cs" />
|
<Compile Include="Commands\CommandModule.cs" />
|
||||||
<Compile Include="Commands\CommandResource.cs" />
|
<Compile Include="Commands\CommandResource.cs" />
|
||||||
|
<Compile Include="Commands\CommandConnection.cs" />
|
||||||
<Compile Include="Config\NamingConfigResource.cs" />
|
<Compile Include="Config\NamingConfigResource.cs" />
|
||||||
<Compile Include="Config\NamingModule.cs" />
|
<Compile Include="Config\NamingModule.cs" />
|
||||||
|
<Compile Include="ProgressMessaging\ProgressMessageConnection.cs" />
|
||||||
|
<Compile Include="ProgressMessaging\ProgressMessageModule.cs" />
|
||||||
|
<Compile Include="ProgressMessaging\ProgressMessageResource.cs" />
|
||||||
<Compile Include="EpisodeFiles\EpisodeFileModule.cs" />
|
<Compile Include="EpisodeFiles\EpisodeFileModule.cs" />
|
||||||
<Compile Include="EpisodeFiles\EpisodeFileResource.cs" />
|
<Compile Include="EpisodeFiles\EpisodeFileResource.cs" />
|
||||||
<Compile Include="Directories\DirectoryLookupService.cs" />
|
<Compile Include="Directories\DirectoryLookupService.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<NewProgressMessageEvent>
|
||||||
|
{
|
||||||
|
public override string Resource
|
||||||
|
{
|
||||||
|
get { return "/ProgressMessage"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleAsync(NewProgressMessageEvent message)
|
||||||
|
{
|
||||||
|
var context = ((ConnectionManager)GlobalHost.ConnectionManager).GetConnection(GetType());
|
||||||
|
context.Connection.Broadcast(message.ProgressMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ProgressMessageResource>
|
||||||
|
{
|
||||||
|
public ProgressMessageModule()
|
||||||
|
{
|
||||||
|
Get["/"] = x => GetAllMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response GetAllMessages()
|
||||||
|
{
|
||||||
|
return new List<ProgressMessageResource>().AsResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,6 +48,23 @@ namespace NzbDrone.Common.Test.CacheTests
|
||||||
_cachedString.Find("Key").Should().Be("New");
|
_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]
|
[Test]
|
||||||
public void should_store_null()
|
public void should_store_null()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Test.EventingTests
|
namespace NzbDrone.Common.Test.EventingTests
|
||||||
|
@ -27,6 +28,13 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
.Setup(c => c.Build(typeof(IExecute<CommandB>)))
|
.Setup(c => c.Build(typeof(IExecute<CommandB>)))
|
||||||
.Returns(_executorB.Object);
|
.Returns(_executorB.Object);
|
||||||
|
|
||||||
|
Mocker.GetMock<ITrackCommands>()
|
||||||
|
.Setup(c => c.TrackIfNew(It.IsAny<CommandA>()))
|
||||||
|
.Returns(new TrackedCommand(new CommandA(), ProcessState.Running));
|
||||||
|
|
||||||
|
Mocker.GetMock<ITrackCommands>()
|
||||||
|
.Setup(c => c.TrackIfNew(It.IsAny<CommandB>()))
|
||||||
|
.Returns(new TrackedCommand(new CommandB(), ProcessState.Running));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -34,6 +42,10 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
{
|
{
|
||||||
var commandA = new CommandA();
|
var commandA = new CommandA();
|
||||||
|
|
||||||
|
Mocker.GetMock<ITrackCommands>()
|
||||||
|
.Setup(c => c.TrackIfNew(commandA))
|
||||||
|
.Returns(new TrackedCommand(commandA, ProcessState.Running));
|
||||||
|
|
||||||
Subject.PublishCommand(commandA);
|
Subject.PublishCommand(commandA);
|
||||||
|
|
||||||
_executorA.Verify(c => c.Execute(commandA), Times.Once());
|
_executorA.Verify(c => c.Execute(commandA), Times.Once());
|
||||||
|
@ -55,6 +67,9 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
{
|
{
|
||||||
var commandA = new CommandA();
|
var commandA = new CommandA();
|
||||||
|
|
||||||
|
Mocker.GetMock<ITrackCommands>()
|
||||||
|
.Setup(c => c.TrackIfNew(commandA))
|
||||||
|
.Returns(new TrackedCommand(commandA, ProcessState.Running));
|
||||||
|
|
||||||
Subject.PublishCommand(commandA);
|
Subject.PublishCommand(commandA);
|
||||||
|
|
||||||
|
@ -76,17 +91,23 @@ namespace NzbDrone.Common.Test.EventingTests
|
||||||
|
|
||||||
public class CommandA : ICommand
|
public class CommandA : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
// ReSharper disable UnusedParameter.Local
|
// ReSharper disable UnusedParameter.Local
|
||||||
public CommandA(int id = 0)
|
public CommandA(int id = 0)
|
||||||
// ReSharper restore UnusedParameter.Local
|
// ReSharper restore UnusedParameter.Local
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CommandB : ICommand
|
public class CommandB : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public CommandB()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,6 +69,7 @@
|
||||||
<Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" />
|
<Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" />
|
||||||
<Compile Include="EventingTests\MessageAggregatorCommandTests.cs" />
|
<Compile Include="EventingTests\MessageAggregatorCommandTests.cs" />
|
||||||
<Compile Include="EventingTests\MessageAggregatorEventTests.cs" />
|
<Compile Include="EventingTests\MessageAggregatorEventTests.cs" />
|
||||||
|
<Compile Include="MessagingTests\CommandEqualityComparerFixture.cs" />
|
||||||
<Compile Include="ReflectionExtensions.cs" />
|
<Compile Include="ReflectionExtensions.cs" />
|
||||||
<Compile Include="PathExtensionFixture.cs" />
|
<Compile Include="PathExtensionFixture.cs" />
|
||||||
<Compile Include="DiskProviderTests\DiskProviderFixture.cs" />
|
<Compile Include="DiskProviderTests\DiskProviderFixture.cs" />
|
||||||
|
|
|
@ -28,7 +28,6 @@ namespace NzbDrone.Common.Cache
|
||||||
return GetCache<T>(host, host.FullName);
|
return GetCache<T>(host, host.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
_cache.Clear();
|
_cache.Clear();
|
||||||
|
|
|
@ -61,6 +61,12 @@ namespace NzbDrone.Common.Cache
|
||||||
return value.Object;
|
return value.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove(string key)
|
||||||
|
{
|
||||||
|
CacheItem value;
|
||||||
|
_store.TryRemove(key, out value);
|
||||||
|
}
|
||||||
|
|
||||||
public T Get(string key, Func<T> function, TimeSpan? lifeTime = null)
|
public T Get(string key, Func<T> function, TimeSpan? lifeTime = null)
|
||||||
{
|
{
|
||||||
Ensure.That(() => key).IsNotNullOrWhiteSpace();
|
Ensure.That(() => key).IsNotNullOrWhiteSpace();
|
||||||
|
@ -81,7 +87,6 @@ namespace NzbDrone.Common.Cache
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
_store.Clear();
|
_store.Clear();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace NzbDrone.Common.Cache
|
||||||
void Set(string key, T value, TimeSpan? lifetime = null);
|
void Set(string key, T value, TimeSpan? lifetime = null);
|
||||||
T Get(string key, Func<T> function, TimeSpan? lifeTime = null);
|
T Get(string key, Func<T> function, TimeSpan? lifeTime = null);
|
||||||
T Find(string key);
|
T Find(string key);
|
||||||
|
void Remove(string key);
|
||||||
|
|
||||||
ICollection<T> Values { get; }
|
ICollection<T> Values { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,31 +34,9 @@ namespace NzbDrone.Common
|
||||||
return String.Format("{0:x8}", mCrc);
|
return String.Format("{0:x8}", mCrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GenerateUserId()
|
public static string GenerateCommandId()
|
||||||
{
|
{
|
||||||
return GenerateId("u");
|
return GenerateId("c");
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GenerateId(string prefix)
|
private static string GenerateId(string prefix)
|
||||||
|
|
|
@ -13,7 +13,6 @@ namespace NzbDrone.Common.Instrumentation
|
||||||
return HashUtil.CalculateCrc(hashSeed);
|
return HashUtil.CalculateCrc(hashSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static string GetFormattedMessage(this LogEventInfo logEvent)
|
public static string GetFormattedMessage(this LogEventInfo logEvent)
|
||||||
{
|
{
|
||||||
var message = logEvent.FormattedMessage;
|
var message = logEvent.FormattedMessage;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
namespace NzbDrone.Common.Messaging
|
|
||||||
{
|
|
||||||
public class CommandCompletedEvent : IEvent
|
|
||||||
{
|
|
||||||
public ICommand Command { get; private set; }
|
|
||||||
|
|
||||||
public CommandCompletedEvent(ICommand command)
|
|
||||||
{
|
|
||||||
Command = command;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<ICommand>
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NzbDrone.Common.Messaging
|
|
||||||
{
|
|
||||||
public class CommandFailedEvent : IEvent
|
|
||||||
{
|
|
||||||
public ICommand Command { get; private set; }
|
|
||||||
public Exception Exception { get; private set; }
|
|
||||||
|
|
||||||
public CommandFailedEvent(ICommand command, Exception exception)
|
|
||||||
{
|
|
||||||
Command = command;
|
|
||||||
Exception = exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
namespace NzbDrone.Common.Messaging
|
|
||||||
{
|
|
||||||
public class CommandExecutedEvent : IEvent
|
|
||||||
{
|
|
||||||
public ICommand Command { get; private set; }
|
|
||||||
|
|
||||||
public CommandExecutedEvent(ICommand command)
|
|
||||||
{
|
|
||||||
Command = command;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Messaging.Events
|
||||||
|
{
|
||||||
|
public class CommandCompletedEvent : IEvent
|
||||||
|
{
|
||||||
|
public TrackedCommand TrackedCommand { get; private set; }
|
||||||
|
|
||||||
|
public CommandCompletedEvent(TrackedCommand trackedCommand)
|
||||||
|
{
|
||||||
|
TrackedCommand = trackedCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Messaging.Events
|
||||||
|
{
|
||||||
|
public class CommandExecutedEvent : IEvent
|
||||||
|
{
|
||||||
|
public TrackedCommand TrackedCommand { get; private set; }
|
||||||
|
|
||||||
|
public CommandExecutedEvent(TrackedCommand trackedCommand)
|
||||||
|
{
|
||||||
|
TrackedCommand = trackedCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Messaging.Events
|
||||||
|
{
|
||||||
|
public class CommandFailedEvent : IEvent
|
||||||
|
{
|
||||||
|
public TrackedCommand TrackedCommand { get; private set; }
|
||||||
|
public Exception Exception { get; private set; }
|
||||||
|
|
||||||
|
public CommandFailedEvent(TrackedCommand trackedCommand, Exception exception)
|
||||||
|
{
|
||||||
|
TrackedCommand = trackedCommand;
|
||||||
|
Exception = exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Messaging.Events
|
||||||
|
{
|
||||||
|
public class CommandStartedEvent : IEvent
|
||||||
|
{
|
||||||
|
public TrackedCommand TrackedCommand { get; private set; }
|
||||||
|
|
||||||
|
public CommandStartedEvent(TrackedCommand trackedCommand)
|
||||||
|
{
|
||||||
|
TrackedCommand = trackedCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Messaging
|
namespace NzbDrone.Common.Messaging
|
||||||
{
|
{
|
||||||
public interface ICommand : IMessage
|
public interface ICommand : IMessage
|
||||||
{
|
{
|
||||||
|
String CommandId { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
namespace NzbDrone.Common.Messaging
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Messaging
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables loosely-coupled publication of events.
|
/// Enables loosely-coupled publication of events.
|
||||||
|
@ -7,6 +9,8 @@
|
||||||
{
|
{
|
||||||
void PublishEvent<TEvent>(TEvent @event) where TEvent : class, IEvent;
|
void PublishEvent<TEvent>(TEvent @event) where TEvent : class, IEvent;
|
||||||
void PublishCommand<TCommand>(TCommand command) where TCommand : class, ICommand;
|
void PublishCommand<TCommand>(TCommand command) where TCommand : class, ICommand;
|
||||||
void PublishCommand(string commandType);
|
void PublishCommand(string commandTypeName);
|
||||||
|
TrackedCommand PublishCommandAsync<TCommand>(TCommand command) where TCommand : class, ICommand;
|
||||||
|
TrackedCommand PublishCommandAsync(string commandTypeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
public interface IProcessMessageAsync : IProcessMessage { }
|
public interface IProcessMessageAsync : IProcessMessage { }
|
||||||
|
|
||||||
|
|
||||||
public interface IProcessMessage<TMessage> : IProcessMessage { }
|
public interface IProcessMessage<TMessage> : IProcessMessage { }
|
||||||
|
|
||||||
public interface IProcessMessageAsync<TMessage> : IProcessMessageAsync { }
|
public interface IProcessMessageAsync<TMessage> : IProcessMessageAsync { }
|
||||||
|
|
|
@ -4,6 +4,8 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
|
using NzbDrone.Common.Messaging.Events;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Common.TPL;
|
using NzbDrone.Common.TPL;
|
||||||
|
|
||||||
|
@ -13,12 +15,14 @@ namespace NzbDrone.Common.Messaging
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
private readonly IServiceFactory _serviceFactory;
|
private readonly IServiceFactory _serviceFactory;
|
||||||
|
private readonly ITrackCommands _trackCommands;
|
||||||
private readonly TaskFactory _taskFactory;
|
private readonly TaskFactory _taskFactory;
|
||||||
|
|
||||||
public MessageAggregator(Logger logger, IServiceFactory serviceFactory)
|
public MessageAggregator(Logger logger, IServiceFactory serviceFactory, ITrackCommands trackCommands)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_serviceFactory = serviceFactory;
|
_serviceFactory = serviceFactory;
|
||||||
|
_trackCommands = trackCommands;
|
||||||
var scheduler = new LimitedConcurrencyLevelTaskScheduler(2);
|
var scheduler = new LimitedConcurrencyLevelTaskScheduler(2);
|
||||||
_taskFactory = new TaskFactory(scheduler);
|
_taskFactory = new TaskFactory(scheduler);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +64,6 @@ namespace NzbDrone.Common.Messaging
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static string GetEventName(Type eventType)
|
private static string GetEventName(Type eventType)
|
||||||
{
|
{
|
||||||
if (!eventType.IsGenericType)
|
if (!eventType.IsGenericType)
|
||||||
|
@ -71,15 +74,69 @@ namespace NzbDrone.Common.Messaging
|
||||||
return string.Format("{0}<{1}>", eventType.Name.Remove(eventType.Name.IndexOf('`')), eventType.GetGenericArguments()[0].Name);
|
return string.Format("{0}<{1}>", eventType.Name.Remove(eventType.Name.IndexOf('`')), eventType.GetGenericArguments()[0].Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void PublishCommand<TCommand>(TCommand command) where TCommand : class, ICommand
|
public void PublishCommand<TCommand>(TCommand command) where TCommand : class, ICommand
|
||||||
{
|
{
|
||||||
Ensure.That(() => command).IsNotNull();
|
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<TCommand>(trackedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PublishCommand(string commandTypeName)
|
||||||
|
{
|
||||||
|
dynamic command = GetCommand(commandTypeName);
|
||||||
|
PublishCommand(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedCommand PublishCommandAsync<TCommand>(TCommand command) where TCommand : class, ICommand
|
||||||
|
{
|
||||||
|
Ensure.That(() => command).IsNotNull();
|
||||||
|
|
||||||
_logger.Trace("Publishing {0}", command.GetType().Name);
|
_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<TCommand>(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<TCommand>(TrackedCommand trackedCommand) where TCommand : class, ICommand
|
||||||
|
{
|
||||||
|
var command = (TCommand)trackedCommand.Command;
|
||||||
|
|
||||||
|
var handlerContract = typeof(IExecute<>).MakeGenericType(command.GetType());
|
||||||
var handler = (IExecute<TCommand>)_serviceFactory.Build(handlerContract);
|
var handler = (IExecute<TCommand>)_serviceFactory.Build(handlerContract);
|
||||||
|
|
||||||
_logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name);
|
_logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name);
|
||||||
|
@ -88,30 +145,27 @@ namespace NzbDrone.Common.Messaging
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
MappedDiagnosticsContext.Set("CommandId", trackedCommand.Command.CommandId);
|
||||||
|
|
||||||
|
PublishEvent(new CommandStartedEvent(trackedCommand));
|
||||||
handler.Execute(command);
|
handler.Execute(command);
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
PublishEvent(new CommandCompletedEvent(command));
|
|
||||||
|
_trackCommands.Completed(trackedCommand, sw.Elapsed);
|
||||||
|
PublishEvent(new CommandCompletedEvent(trackedCommand));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
PublishEvent(new CommandFailedEvent(command, e));
|
_trackCommands.Failed(trackedCommand, e);
|
||||||
|
PublishEvent(new CommandFailedEvent(trackedCommand, e));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
PublishEvent(new CommandExecutedEvent(command));
|
PublishEvent(new CommandExecutedEvent(trackedCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("{0} <- {1} [{2}]", command.GetType().Name, handler.GetType().Name, sw.Elapsed.ToString(""));
|
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
namespace NzbDrone.Common.Messaging
|
using System;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Messaging
|
||||||
{
|
{
|
||||||
public class TestCommand : ICommand
|
public class TestCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public int Duration { get; set; }
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
public TestCommand()
|
public TestCommand()
|
||||||
{
|
{
|
||||||
Duration = 4000;
|
Duration = 4000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Duration { get; set; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Remoting;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
|
||||||
|
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<TrackedCommand> AllTracked();
|
||||||
|
Boolean ExistingCommand(ICommand command);
|
||||||
|
TrackedCommand FindExisting(ICommand command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TrackCommands : ITrackCommands, IExecute<TrackedCommandCleanupCommand>
|
||||||
|
{
|
||||||
|
private readonly ICached<TrackedCommand> _cache;
|
||||||
|
|
||||||
|
public TrackCommands(ICacheManger cacheManger)
|
||||||
|
{
|
||||||
|
_cache = cacheManger.GetCache<TrackedCommand>(GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedCommand TrackIfNew(ICommand command)
|
||||||
|
{
|
||||||
|
if (ExistingCommand(command))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trackedCommand = new TrackedCommand(command, ProcessState.Running);
|
||||||
|
Store(trackedCommand);
|
||||||
|
|
||||||
|
return trackedCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExistingCommand TrackNewOrGet(ICommand command)
|
||||||
|
{
|
||||||
|
var trackedCommand = FindExisting(command);
|
||||||
|
|
||||||
|
if (trackedCommand == null)
|
||||||
|
{
|
||||||
|
trackedCommand = new TrackedCommand(command, ProcessState.Running);
|
||||||
|
Store(trackedCommand);
|
||||||
|
|
||||||
|
return new ExistingCommand(false, trackedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ExistingCommand(true, trackedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime)
|
||||||
|
{
|
||||||
|
trackedCommand.StateChangeTime = DateTime.UtcNow;
|
||||||
|
trackedCommand.State = ProcessState.Completed;
|
||||||
|
trackedCommand.Runtime = runtime;
|
||||||
|
|
||||||
|
Store(trackedCommand);
|
||||||
|
|
||||||
|
return trackedCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedCommand Failed(TrackedCommand trackedCommand, Exception e)
|
||||||
|
{
|
||||||
|
trackedCommand.StateChangeTime = DateTime.UtcNow;
|
||||||
|
trackedCommand.State = ProcessState.Failed;
|
||||||
|
trackedCommand.Exception = e;
|
||||||
|
|
||||||
|
Store(trackedCommand);
|
||||||
|
|
||||||
|
return trackedCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TrackedCommand> AllTracked()
|
||||||
|
{
|
||||||
|
return _cache.Values.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExistingCommand(ICommand command)
|
||||||
|
{
|
||||||
|
return FindExisting(command) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedCommand FindExisting(ICommand command)
|
||||||
|
{
|
||||||
|
var comparer = new CommandEqualityComparer();
|
||||||
|
return Running(command.GetType()).SingleOrDefault(t => comparer.Equals(t.Command, command));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TrackedCommand> Running(Type type = null)
|
||||||
|
{
|
||||||
|
var running = AllTracked().Where(i => i.State == ProcessState.Running);
|
||||||
|
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
return running.Where(t => t.Type == type.FullName).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return running.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.State != ProcessState.Running && c.StateChangeTime < DateTime.UtcNow.AddMinutes(-5));
|
||||||
|
|
||||||
|
foreach (var trackedCommand in old)
|
||||||
|
{
|
||||||
|
_cache.Remove(trackedCommand.Command.CommandId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
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 ProcessState State { get; set; }
|
||||||
|
public DateTime StateChangeTime { get; set; }
|
||||||
|
public TimeSpan Runtime { get; set; }
|
||||||
|
public Exception Exception { get; set; }
|
||||||
|
|
||||||
|
public TrackedCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackedCommand(ICommand command, ProcessState state)
|
||||||
|
{
|
||||||
|
Id = command.CommandId;
|
||||||
|
Name = command.GetType().Name;
|
||||||
|
Type = command.GetType().FullName;
|
||||||
|
Command = command;
|
||||||
|
State = state;
|
||||||
|
StateChangeTime = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,6 +94,14 @@
|
||||||
<Compile Include="Instrumentation\ExceptronTarget.cs" />
|
<Compile Include="Instrumentation\ExceptronTarget.cs" />
|
||||||
<Compile Include="Instrumentation\NzbDroneLogger.cs" />
|
<Compile Include="Instrumentation\NzbDroneLogger.cs" />
|
||||||
<Compile Include="Instrumentation\LogTargets.cs" />
|
<Compile Include="Instrumentation\LogTargets.cs" />
|
||||||
|
<Compile Include="Instrumentation\LoggerExtensions.cs" />
|
||||||
|
<Compile Include="Messaging\Tracking\ProcessState.cs" />
|
||||||
|
<Compile Include="Messaging\Tracking\CommandTrackingService.cs" />
|
||||||
|
<Compile Include="Messaging\Tracking\ExistingCommand.cs" />
|
||||||
|
<Compile Include="Messaging\Tracking\TrackedCommand.cs" />
|
||||||
|
<Compile Include="Messaging\Events\CommandStartedEvent.cs" />
|
||||||
|
<Compile Include="Messaging\CommandEqualityComparer.cs" />
|
||||||
|
<Compile Include="Messaging\Tracking\TrackedCommandCleanupCommand.cs" />
|
||||||
<Compile Include="PathEqualityComparer.cs" />
|
<Compile Include="PathEqualityComparer.cs" />
|
||||||
<Compile Include="Services.cs" />
|
<Compile Include="Services.cs" />
|
||||||
<Compile Include="TPL\LimitedConcurrencyLevelTaskScheduler.cs" />
|
<Compile Include="TPL\LimitedConcurrencyLevelTaskScheduler.cs" />
|
||||||
|
@ -104,9 +112,9 @@
|
||||||
<Compile Include="Instrumentation\LogEventExtensions.cs" />
|
<Compile Include="Instrumentation\LogEventExtensions.cs" />
|
||||||
<Compile Include="Instrumentation\LogglyTarget.cs" />
|
<Compile Include="Instrumentation\LogglyTarget.cs" />
|
||||||
<Compile Include="Serializer\Json.cs" />
|
<Compile Include="Serializer\Json.cs" />
|
||||||
<Compile Include="Messaging\CommandCompletedEvent.cs" />
|
<Compile Include="Messaging\Events\CommandCompletedEvent.cs" />
|
||||||
<Compile Include="Messaging\CommandStartedEvent.cs" />
|
<Compile Include="Messaging\Events\CommandExecutedEvent.cs" />
|
||||||
<Compile Include="Messaging\CommandFailedEvent.cs" />
|
<Compile Include="Messaging\Events\CommandFailedEvent.cs" />
|
||||||
<Compile Include="Messaging\IExecute.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" />
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
[TestCase("Top_Gear.19x06.720p_HDTV_x264-FoV", "Top Gear", 19, 6)]
|
[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("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("(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)
|
public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber)
|
||||||
{
|
{
|
||||||
var result = Parser.Parser.ParseTitle(postTitle);
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DataAugmentation.Scene
|
namespace NzbDrone.Core.DataAugmentation.Scene
|
||||||
{
|
{
|
||||||
public class UpdateSceneMappingCommand : ICommand
|
public class UpdateSceneMappingCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public UpdateSceneMappingCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,17 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.IndexerSearch
|
namespace NzbDrone.Core.IndexerSearch
|
||||||
{
|
{
|
||||||
public class EpisodeSearchCommand : ICommand
|
public class EpisodeSearchCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public int EpisodeId { get; set; }
|
public int EpisodeId { get; set; }
|
||||||
|
|
||||||
|
public EpisodeSearchCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,18 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.IndexerSearch
|
namespace NzbDrone.Core.IndexerSearch
|
||||||
{
|
{
|
||||||
public class SeasonSearchCommand : ICommand
|
public class SeasonSearchCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
public int SeasonNumber { get; set; }
|
public int SeasonNumber { get; set; }
|
||||||
|
|
||||||
|
public SeasonSearchCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,17 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.IndexerSearch
|
namespace NzbDrone.Core.IndexerSearch
|
||||||
{
|
{
|
||||||
public class SeriesSearchCommand : ICommand
|
public class SeriesSearchCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
|
|
||||||
|
public SeriesSearchCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,16 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers
|
namespace NzbDrone.Core.Indexers
|
||||||
{
|
{
|
||||||
public class RssSyncCommand : ICommand
|
public class RssSyncCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public RssSyncCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Instrumentation;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
@ -38,7 +39,7 @@ namespace NzbDrone.Core.Indexers
|
||||||
var decisions = _downloadDecisionMaker.GetRssDecision(reports);
|
var decisions = _downloadDecisionMaker.GetRssDecision(reports);
|
||||||
var qualifiedReports = _downloadApprovedReports.DownloadApproved(decisions);
|
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)
|
public void Execute(RssSyncCommand message)
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Instrumentation.Commands
|
namespace NzbDrone.Core.Instrumentation.Commands
|
||||||
{
|
{
|
||||||
public class ClearLogCommand : ICommand
|
public class ClearLogCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public ClearLogCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,16 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Instrumentation.Commands
|
namespace NzbDrone.Core.Instrumentation.Commands
|
||||||
{
|
{
|
||||||
public class DeleteLogFilesCommand : ICommand
|
public class DeleteLogFilesCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public DeleteLogFilesCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,16 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Instrumentation.Commands
|
namespace NzbDrone.Core.Instrumentation.Commands
|
||||||
{
|
{
|
||||||
public class TrimLogCommand : ICommand
|
public class TrimLogCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public TrimLogCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Common.Messaging.Events;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Configuration.Events;
|
using NzbDrone.Core.Configuration.Events;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
@ -47,7 +49,8 @@ namespace NzbDrone.Core.Jobs
|
||||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName},
|
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName},
|
||||||
new ScheduledTask{ Interval = 1, TypeName = typeof(DownloadedEpisodesScanCommand).FullName},
|
new ScheduledTask{ Interval = 1, TypeName = typeof(DownloadedEpisodesScanCommand).FullName},
|
||||||
new ScheduledTask{ Interval = 60, TypeName = typeof(ApplicationUpdateCommand).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 = 1, TypeName = typeof(TrackedCommandCleanupCommand).FullName}
|
||||||
};
|
};
|
||||||
|
|
||||||
var currentTasks = _scheduledTaskRepository.All();
|
var currentTasks = _scheduledTaskRepository.All();
|
||||||
|
@ -76,7 +79,7 @@ namespace NzbDrone.Core.Jobs
|
||||||
|
|
||||||
public void HandleAsync(CommandExecutedEvent 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)
|
if (scheduledTask != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,5 +6,4 @@ namespace NzbDrone.Core.Lifecycle
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,13 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.Commands
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
{
|
{
|
||||||
public class CleanMediaFileDb : ICommand
|
public class CleanMediaFileDb : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public int SeriesId { get; private set; }
|
public int SeriesId { get; private set; }
|
||||||
|
|
||||||
|
public CleanMediaFileDb()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
|
|
||||||
public CleanMediaFileDb(int seriesId)
|
public CleanMediaFileDb(int seriesId)
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
SeriesId = seriesId;
|
SeriesId = seriesId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.Commands
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
{
|
{
|
||||||
public class CleanUpRecycleBinCommand : ICommand
|
public class CleanUpRecycleBinCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public CleanUpRecycleBinCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.Commands
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
{
|
{
|
||||||
public class DownloadedEpisodesScanCommand : ICommand
|
public class DownloadedEpisodesScanCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
public DownloadedEpisodesScanCommand()
|
public DownloadedEpisodesScanCommand()
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.Commands
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
{
|
{
|
||||||
public class RenameSeasonCommand : ICommand
|
public class RenameSeasonCommand : ICommand
|
||||||
{
|
{
|
||||||
public int SeriesId { get; private set; }
|
public int SeriesId { get; set; }
|
||||||
public int SeasonNumber { get; private set; }
|
public int SeasonNumber { get; set; }
|
||||||
|
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public RenameSeasonCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
|
|
||||||
public RenameSeasonCommand(int seriesId, int seasonNumber)
|
public RenameSeasonCommand(int seriesId, int seasonNumber)
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
SeriesId = seriesId;
|
SeriesId = seriesId;
|
||||||
SeasonNumber = seasonNumber;
|
SeasonNumber = seasonNumber;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.Commands
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
{
|
{
|
||||||
public class RenameSeriesCommand : ICommand
|
public class RenameSeriesCommand : ICommand
|
||||||
{
|
{
|
||||||
public int SeriesId { get; private set; }
|
public String CommandId { get; private set; }
|
||||||
|
public int SeriesId { get; set; }
|
||||||
|
|
||||||
|
public RenameSeriesCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
|
|
||||||
public RenameSeriesCommand(int seriesId)
|
public RenameSeriesCommand(int seriesId)
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
SeriesId = seriesId;
|
SeriesId = seriesId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Email
|
namespace NzbDrone.Core.Notifications.Email
|
||||||
{
|
{
|
||||||
public class TestEmailCommand : ICommand
|
public class TestEmailCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string Server { get; set; }
|
public string Server { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public bool Ssl { get; set; }
|
public bool Ssl { get; set; }
|
||||||
|
@ -11,5 +14,10 @@ namespace NzbDrone.Core.Notifications.Email
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public string From { get; set; }
|
public string From { get; set; }
|
||||||
public string To { get; set; }
|
public string To { get; set; }
|
||||||
|
|
||||||
|
public TestEmailCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Growl
|
namespace NzbDrone.Core.Notifications.Growl
|
||||||
{
|
{
|
||||||
public class TestGrowlCommand : ICommand
|
public class TestGrowlCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public TestGrowlCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Plex
|
namespace NzbDrone.Core.Notifications.Plex
|
||||||
{
|
{
|
||||||
public class TestPlexClientCommand : ICommand
|
public class TestPlexClientCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public TestPlexClientCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Plex
|
namespace NzbDrone.Core.Notifications.Plex
|
||||||
{
|
{
|
||||||
public class TestPlexServerCommand : ICommand
|
public class TestPlexServerCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
public TestPlexServerCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Prowl
|
namespace NzbDrone.Core.Notifications.Prowl
|
||||||
{
|
{
|
||||||
public class TestProwlCommand : ICommand
|
public class TestProwlCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
public TestProwlCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Pushover
|
namespace NzbDrone.Core.Notifications.Pushover
|
||||||
{
|
{
|
||||||
public class TestPushoverCommand : ICommand
|
public class TestPushoverCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string UserKey { get; set; }
|
public string UserKey { get; set; }
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
public TestPushoverCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Xbmc
|
namespace NzbDrone.Core.Notifications.Xbmc
|
||||||
{
|
{
|
||||||
public class TestXbmcCommand : ICommand
|
public class TestXbmcCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
public string Host { get; set; }
|
public string Host { get; set; }
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public int DisplayTime { get; set; }
|
public int DisplayTime { get; set; }
|
||||||
|
|
||||||
|
public TestXbmcCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,9 @@
|
||||||
<Compile Include="Instrumentation\Commands\DeleteLogFilesCommand.cs" />
|
<Compile Include="Instrumentation\Commands\DeleteLogFilesCommand.cs" />
|
||||||
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
<Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
|
||||||
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
<Compile Include="Instrumentation\DeleteLogFilesService.cs" />
|
||||||
|
<Compile Include="ProgressMessaging\NewProgressMessageEvent.cs" />
|
||||||
|
<Compile Include="ProgressMessaging\ProgressMessage.cs" />
|
||||||
|
<Compile Include="ProgressMessaging\ProgressMessageTarget.cs" />
|
||||||
<Compile Include="Instrumentation\SetLoggingLevel.cs" />
|
<Compile Include="Instrumentation\SetLoggingLevel.cs" />
|
||||||
<Compile Include="Jobs\TaskManager.cs" />
|
<Compile Include="Jobs\TaskManager.cs" />
|
||||||
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
|
<Compile Include="Lifecycle\ApplicationShutdownRequested.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.ProgressMessaging
|
||||||
|
{
|
||||||
|
public class ProgressMessage
|
||||||
|
{
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
public String CommandId { get; set; }
|
||||||
|
public String Message { get; set; }
|
||||||
|
public ProcessState Status { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
using System;
|
||||||
|
using NLog.Config;
|
||||||
|
using NLog;
|
||||||
|
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 ProgressMessageTarget : TargetWithLayout, IHandle<ApplicationStartedEvent>, IHandle<ApplicationShutdownRequested>
|
||||||
|
{
|
||||||
|
private readonly IMessageAggregator _messageAggregator;
|
||||||
|
public LoggingRule Rule { get; set; }
|
||||||
|
|
||||||
|
public ProgressMessageTarget(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 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(ApplicationStartedEvent message)
|
||||||
|
{
|
||||||
|
if (!LogManager.Configuration.LoggingRules.Contains(Rule))
|
||||||
|
{
|
||||||
|
Register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(ApplicationShutdownRequested message)
|
||||||
|
{
|
||||||
|
if (LogManager.Configuration.LoggingRules.Contains(Rule))
|
||||||
|
{
|
||||||
|
UnRegister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,17 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Providers
|
namespace NzbDrone.Core.Providers
|
||||||
{
|
{
|
||||||
public class UpdateXemMappingsCommand : ICommand
|
public class UpdateXemMappingsCommand : ICommand
|
||||||
{
|
{
|
||||||
public int? SeriesId { get; private set; }
|
public String CommandId { get; private set; }
|
||||||
|
public int? SeriesId { get; set; }
|
||||||
|
|
||||||
public UpdateXemMappingsCommand(int? seriesId)
|
public UpdateXemMappingsCommand(int? seriesId)
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
SeriesId = seriesId;
|
SeriesId = seriesId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,8 +132,7 @@ namespace NzbDrone.Core.Providers
|
||||||
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//TODO: We should increase this back to warn when caching is in place
|
_logger.ErrorException("Error updating scene numbering mappings for: " + series, ex);
|
||||||
_logger.TraceException("Error updating scene numbering mappings for: " + series, ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Tv.Commands
|
namespace NzbDrone.Core.Tv.Commands
|
||||||
{
|
{
|
||||||
public class RefreshSeriesCommand : ICommand
|
public class RefreshSeriesCommand : ICommand
|
||||||
{
|
{
|
||||||
public int? SeriesId { get; private set; }
|
public String CommandId { get; private set; }
|
||||||
|
public int? SeriesId { get; set; }
|
||||||
|
|
||||||
|
public RefreshSeriesCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
|
|
||||||
public RefreshSeriesCommand(int? seriesId)
|
public RefreshSeriesCommand(int? seriesId)
|
||||||
{
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
|
||||||
SeriesId = seriesId;
|
SeriesId = seriesId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using System;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Update.Commands
|
namespace NzbDrone.Core.Update.Commands
|
||||||
{
|
{
|
||||||
public class ApplicationUpdateCommand : ICommand
|
public class ApplicationUpdateCommand : ICommand
|
||||||
{
|
{
|
||||||
|
public String CommandId { get; private set; }
|
||||||
|
|
||||||
|
public ApplicationUpdateCommand()
|
||||||
|
{
|
||||||
|
CommandId = HashUtil.GenerateCommandId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
using NUnit.Framework;
|
using System.Net;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
using NzbDrone.Api.Commands;
|
using NzbDrone.Api.Commands;
|
||||||
|
using NzbDrone.Common.Messaging.Tracking;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using RestSharp;
|
||||||
|
|
||||||
namespace NzbDrone.Integration.Test
|
namespace NzbDrone.Integration.Test
|
||||||
{
|
{
|
||||||
|
@ -9,7 +14,27 @@ namespace NzbDrone.Integration.Test
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_able_to_run_rss_sync()
|
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<TrackedCommand>(response.Content);
|
||||||
|
trackedCommand.Id.Should().NotBeNullOrEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'backbone'
|
||||||
|
], function (Backbone) {
|
||||||
|
return Backbone.Model.extend({
|
||||||
|
});
|
||||||
|
});
|
|
@ -9,9 +9,9 @@ define(
|
||||||
'Series/SeriesCollection',
|
'Series/SeriesCollection',
|
||||||
'Shared/LoadingView',
|
'Shared/LoadingView',
|
||||||
'Shared/Messenger',
|
'Shared/Messenger',
|
||||||
'Commands/CommandController',
|
'Shared/Actioneer',
|
||||||
'Shared/FormatHelpers'
|
'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({
|
return Marionette.Layout.extend({
|
||||||
template: 'Episode/Search/LayoutTemplate',
|
template: 'Episode/Search/LayoutTemplate',
|
||||||
|
@ -39,16 +39,19 @@ define(
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandController.Execute('episodeSearch', { episodeId: this.model.get('id') });
|
|
||||||
|
|
||||||
var series = SeriesCollection.get(this.model.get('seriesId'));
|
var series = SeriesCollection.get(this.model.get('seriesId'));
|
||||||
var seriesTitle = series.get('title');
|
var seriesTitle = series.get('title');
|
||||||
var season = this.model.get('seasonNumber');
|
var season = this.model.get('seasonNumber');
|
||||||
var episode = this.model.get('episodeNumber');
|
var episode = this.model.get('episodeNumber');
|
||||||
var message = seriesTitle + ' - ' + season + 'x' + FormatHelpers.pad(episode, 2);
|
var message = seriesTitle + ' - ' + season + 'x' + FormatHelpers.pad(episode, 2);
|
||||||
|
|
||||||
Messenger.show({
|
Actioneer.ExecuteCommand({
|
||||||
message: 'Search started for: ' + message
|
command : 'episodeSearch',
|
||||||
|
properties : {
|
||||||
|
episodeId: this.model.get('id')
|
||||||
|
},
|
||||||
|
errorMessage: 'Search failed for: ' + message,
|
||||||
|
startMessage: 'Search started for: ' + message
|
||||||
});
|
});
|
||||||
|
|
||||||
App.vent.trigger(App.Commands.CloseModalCommand);
|
App.vent.trigger(App.Commands.CloseModalCommand);
|
||||||
|
|
|
@ -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;
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'backbone'
|
||||||
|
], function (Backbone) {
|
||||||
|
return Backbone.Model.extend({
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,10 +5,12 @@ require(
|
||||||
'marionette',
|
'marionette',
|
||||||
'Controller',
|
'Controller',
|
||||||
'Series/SeriesCollection',
|
'Series/SeriesCollection',
|
||||||
|
'ProgressMessaging/ProgressMessageCollection',
|
||||||
|
'Shared/Actioneer',
|
||||||
'Navbar/NavbarView',
|
'Navbar/NavbarView',
|
||||||
'jQuery/RouteBinder',
|
'jQuery/RouteBinder',
|
||||||
'jquery'
|
'jquery'
|
||||||
], function (App, Marionette, Controller, SeriesCollection, NavbarView, RouterBinder, $) {
|
], function (App, Marionette, Controller, SeriesCollection, ProgressMessageCollection, Actioneer, NavbarView, RouterBinder, $) {
|
||||||
|
|
||||||
var Router = Marionette.AppRouter.extend({
|
var Router = Marionette.AppRouter.extend({
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ require(
|
||||||
RouterBinder.bind(App.Router);
|
RouterBinder.bind(App.Router);
|
||||||
App.navbarRegion.show(new NavbarView());
|
App.navbarRegion.show(new NavbarView());
|
||||||
$('body').addClass('started');
|
$('body').addClass('started');
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return App.Router;
|
return App.Router;
|
||||||
|
|
|
@ -113,6 +113,8 @@ define(
|
||||||
},
|
},
|
||||||
|
|
||||||
_setMonitored: function (seasonNumber) {
|
_setMonitored: function (seasonNumber) {
|
||||||
|
//TODO: use Actioneer?
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var promise = $.ajax({
|
var promise = $.ajax({
|
||||||
|
|
|
@ -8,9 +8,8 @@ define(
|
||||||
'Cells/EpisodeTitleCell',
|
'Cells/EpisodeTitleCell',
|
||||||
'Cells/RelativeDateCell',
|
'Cells/RelativeDateCell',
|
||||||
'Cells/EpisodeStatusCell',
|
'Cells/EpisodeStatusCell',
|
||||||
'Commands/CommandController',
|
|
||||||
'Shared/Actioneer'
|
'Shared/Actioneer'
|
||||||
], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, CommandController, Actioneer) {
|
], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, Actioneer) {
|
||||||
return Marionette.Layout.extend({
|
return Marionette.Layout.extend({
|
||||||
template: 'Series/Details/SeasonLayoutTemplate',
|
template: 'Series/Details/SeasonLayoutTemplate',
|
||||||
|
|
||||||
|
@ -104,8 +103,9 @@ define(
|
||||||
seasonNumber: this.model.get('seasonNumber')
|
seasonNumber: this.model.get('seasonNumber')
|
||||||
},
|
},
|
||||||
element : this.ui.seasonSearch,
|
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'))
|
startMessage : 'Search for season {0} started'.format(this.model.get('seasonNumber')),
|
||||||
|
successMessage: 'Search for season {0} completed'.format(this.model.get('seasonNumber'))
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ define(
|
||||||
seasonNumber: this.model.get('seasonNumber')
|
seasonNumber: this.model.get('seasonNumber')
|
||||||
},
|
},
|
||||||
element : this.ui.seasonRename,
|
element : this.ui.seasonRename,
|
||||||
failMessage: 'Season rename failed',
|
errorMessage: 'Season rename failed',
|
||||||
context : this,
|
context : this,
|
||||||
onSuccess : this._afterRename
|
onSuccess : this._afterRename
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,7 +51,7 @@ define(
|
||||||
seasonNumber: this.model.get('seasonNumber')
|
seasonNumber: this.model.get('seasonNumber')
|
||||||
},
|
},
|
||||||
element : this.ui.seasonSearch,
|
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'))
|
startMessage: 'Search for season {0} started'.format(this.model.get('seasonNumber'))
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -158,7 +158,7 @@ define(
|
||||||
element : this.ui.rename,
|
element : this.ui.rename,
|
||||||
context : this,
|
context : this,
|
||||||
onSuccess : this._refetchEpisodeFiles,
|
onSuccess : this._refetchEpisodeFiles,
|
||||||
failMessage: 'Series search failed'
|
errorMessage: 'Series search failed'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ define(
|
||||||
seriesId: this.model.get('id')
|
seriesId: this.model.get('id')
|
||||||
},
|
},
|
||||||
element : this.ui.search,
|
element : this.ui.search,
|
||||||
failMessage : 'Series search failed',
|
errorMessage: 'Series search failed',
|
||||||
startMessage: 'Search for {0} started'.format(this.model.get('title'))
|
startMessage: 'Search for {0} started'.format(this.model.get('title'))
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -105,7 +105,6 @@ define(
|
||||||
title : 'RSS Sync',
|
title : 'RSS Sync',
|
||||||
icon : 'icon-rss',
|
icon : 'icon-rss',
|
||||||
command : 'rsssync',
|
command : 'rsssync',
|
||||||
successMessage: 'RSS Sync Completed',
|
|
||||||
errorMessage : 'RSS Sync Failed!'
|
errorMessage : 'RSS Sync Failed!'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -140,7 +139,6 @@ define(
|
||||||
this._fetchCollection();
|
this._fetchCollection();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
this.seriesCollection = SeriesCollection;
|
this.seriesCollection = SeriesCollection;
|
||||||
|
|
||||||
|
@ -148,7 +146,6 @@ define(
|
||||||
this.listenTo(SeriesCollection, 'remove', this._renderView);
|
this.listenTo(SeriesCollection, 'remove', this._renderView);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
_renderView: function () {
|
_renderView: function () {
|
||||||
|
|
||||||
if (SeriesCollection.length === 0) {
|
if (SeriesCollection.length === 0) {
|
||||||
|
@ -164,7 +161,6 @@ define(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
onShow: function () {
|
onShow: function () {
|
||||||
this._showToolbar();
|
this._showToolbar();
|
||||||
this._renderView();
|
this._renderView();
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<button class="btn pull-left x-back">back</button>
|
<button class="btn pull-left x-back">back</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<button class="btn x-test">test <i class="x-test-icon"/></button>
|
<button class="btn x-test">test <i class="x-test-icon icon-nd-test"/></button>
|
||||||
<button class="btn" data-dismiss="modal">cancel</button>
|
<button class="btn" data-dismiss="modal">cancel</button>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
|
|
@ -6,11 +6,11 @@ define([
|
||||||
'Settings/Notifications/Model',
|
'Settings/Notifications/Model',
|
||||||
'Settings/Notifications/DeleteView',
|
'Settings/Notifications/DeleteView',
|
||||||
'Shared/Messenger',
|
'Shared/Messenger',
|
||||||
'Commands/CommandController',
|
'Shared/Actioneer',
|
||||||
'Mixins/AsModelBoundView',
|
'Mixins/AsModelBoundView',
|
||||||
'Form/FormBuilder'
|
'Form/FormBuilder'
|
||||||
|
|
||||||
], function (App, Marionette, NotificationModel, DeleteView, Messenger, CommandController, AsModelBoundView) {
|
], function (App, Marionette, NotificationModel, DeleteView, Messenger, Actioneer, AsModelBoundView) {
|
||||||
|
|
||||||
var model = Marionette.ItemView.extend({
|
var model = Marionette.ItemView.extend({
|
||||||
template: 'Settings/Notifications/EditTemplate',
|
template: 'Settings/Notifications/EditTemplate',
|
||||||
|
@ -70,41 +70,28 @@ define([
|
||||||
var testCommand = this.model.get('testCommand');
|
var testCommand = this.model.get('testCommand');
|
||||||
if (testCommand) {
|
if (testCommand) {
|
||||||
this.idle = false;
|
this.idle = false;
|
||||||
this.ui.testButton.addClass('disabled');
|
|
||||||
this.ui.testIcon.addClass('icon-spinner icon-spin');
|
|
||||||
|
|
||||||
var properties = {};
|
var properties = {};
|
||||||
|
|
||||||
_.each(this.model.get('fields'), function (field) {
|
_.each(this.model.get('fields'), function (field) {
|
||||||
properties[field.name] = field.value;
|
properties[field.name] = field.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
var self = this;
|
Actioneer.ExecuteCommand({
|
||||||
var commandPromise = CommandController.Execute(testCommand, properties);
|
command : testCommand,
|
||||||
commandPromise.done(function () {
|
properties : properties,
|
||||||
Messenger.show({
|
button : this.ui.testButton,
|
||||||
message: 'Notification settings tested successfully'
|
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({
|
_testOnAlways: function () {
|
||||||
message: 'Failed to test notification settings',
|
if (!this.isClosed) {
|
||||||
type : 'error'
|
this.idle = true;
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
commandPromise.always(function () {
|
|
||||||
if (!self.isClosed) {
|
|
||||||
self.ui.testButton.removeClass('disabled');
|
|
||||||
self.ui.testIcon.removeClass('icon-spinner icon-spin');
|
|
||||||
self.idle = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +1,30 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
define(['Commands/CommandController', 'Shared/Messenger'],
|
define(
|
||||||
function(CommandController, Messenger) {
|
[
|
||||||
return {
|
'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) {
|
ExecuteCommand: function (options) {
|
||||||
options.iconClass = this._getIconClass(options.element);
|
options.iconClass = this._getIconClass(options.element);
|
||||||
|
|
||||||
this._showStartMessage(options);
|
if (options.button) {
|
||||||
|
options.button.addClass('disable');
|
||||||
|
}
|
||||||
|
|
||||||
this._setSpinnerOnElement(options);
|
this._setSpinnerOnElement(options);
|
||||||
|
|
||||||
var promise = CommandController.Execute(options.command, options.properties);
|
var promise = CommandController.Execute(options.command, options.properties);
|
||||||
this._handlePromise(promise, options);
|
this._showStartMessage(options, promise);
|
||||||
},
|
},
|
||||||
|
|
||||||
SaveModel: function (options) {
|
SaveModel: function (options) {
|
||||||
|
@ -24,15 +39,7 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||||
|
|
||||||
_handlePromise: function (promise, options) {
|
_handlePromise: function (promise, options) {
|
||||||
promise.done(function () {
|
promise.done(function () {
|
||||||
if (options.successMessage) {
|
self._onSuccess(options);
|
||||||
Messenger.show({
|
|
||||||
message: options.successMessage
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.onSuccess) {
|
|
||||||
options.onSuccess.call(options.context);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.fail(function (ajaxOptions) {
|
promise.fail(function (ajaxOptions) {
|
||||||
|
@ -40,31 +47,46 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.failMessage) {
|
self._onError(options);
|
||||||
Messenger.show({
|
|
||||||
message: options.failMessage,
|
|
||||||
type : 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.onError) {
|
|
||||||
options.onError.call(options.context);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.always(function () {
|
promise.always(function () {
|
||||||
|
self._onComplete(options);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
if (options.leaveIcon) {
|
_handleCommands: function () {
|
||||||
options.element.removeClass('icon-spin');
|
var self = this;
|
||||||
|
|
||||||
|
_.each(this.trackedCommands, function (trackedCommand){
|
||||||
|
if (trackedCommand.completed === true) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
var options = trackedCommand.options;
|
||||||
options.element.addClass(options.iconClass);
|
var command = CommandCollection.find({ 'id': trackedCommand.id });
|
||||||
options.element.removeClass('icon-nd-spinner');
|
|
||||||
|
if (!command) {
|
||||||
|
trackedCommand.completed = true;
|
||||||
|
|
||||||
|
self._onError(options, trackedCommand.id);
|
||||||
|
self._onComplete(options);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.always) {
|
if (command.get('state') === 'completed') {
|
||||||
options.always.call(options.context);
|
trackedCommand.completed = true;
|
||||||
|
|
||||||
|
self._onSuccess(options, command.get('id'));
|
||||||
|
self._onComplete(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.get('state') === 'failed') {
|
||||||
|
trackedCommand.completed = true;
|
||||||
|
|
||||||
|
self._onError(options, command.get('id'));
|
||||||
|
self._onComplete(options);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -74,6 +96,10 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||||
},
|
},
|
||||||
|
|
||||||
_setSpinnerOnElement: function (options) {
|
_setSpinnerOnElement: function (options) {
|
||||||
|
if (!options.element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.leaveIcon) {
|
if (options.leaveIcon) {
|
||||||
options.element.addClass('icon-spin');
|
options.element.addClass('icon-spin');
|
||||||
}
|
}
|
||||||
|
@ -84,12 +110,79 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_showStartMessage: function (options) {
|
_onSuccess: function (options, id) {
|
||||||
|
if (options.successMessage) {
|
||||||
|
Messenger.show({
|
||||||
|
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) {
|
if (options.startMessage) {
|
||||||
Messenger.show({
|
Messenger.show({
|
||||||
message: options.startMessage
|
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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,10 @@ define(function () {
|
||||||
options.hideAfter = 5;
|
options.hideAfter = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'success':
|
||||||
|
options.hideAfter = 5;
|
||||||
|
break;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
options.hideAfter = 0;
|
options.hideAfter = 0;
|
||||||
}
|
}
|
||||||
|
@ -22,11 +26,11 @@ define(function () {
|
||||||
message : options.message,
|
message : options.message,
|
||||||
type : options.type,
|
type : options.type,
|
||||||
showCloseButton: true,
|
showCloseButton: true,
|
||||||
hideAfter : options.hideAfter
|
hideAfter : options.hideAfter,
|
||||||
|
id : options.id
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
monitor: function (options) {
|
monitor: function (options) {
|
||||||
|
|
||||||
if (!options.promise) {
|
if (!options.promise) {
|
||||||
|
|
|
@ -3,9 +3,9 @@ define(
|
||||||
[
|
[
|
||||||
'app',
|
'app',
|
||||||
'marionette',
|
'marionette',
|
||||||
'Commands/CommandController',
|
'Shared/Actioneer',
|
||||||
'Shared/Messenger'
|
'Shared/Messenger'
|
||||||
], function (App, Marionette, CommandController, Messenger) {
|
], function (App, Marionette, Actioneer, Messenger) {
|
||||||
|
|
||||||
return Marionette.ItemView.extend({
|
return Marionette.ItemView.extend({
|
||||||
template : 'Shared/Toolbar/ButtonTemplate',
|
template : 'Shared/Toolbar/ButtonTemplate',
|
||||||
|
@ -19,7 +19,6 @@ define(
|
||||||
icon: '.x-icon'
|
icon: '.x-icon'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
this.storageKey = this.model.get('menuKey') + ':' + this.model.get('key');
|
this.storageKey = this.model.get('menuKey') + ':' + this.model.get('key');
|
||||||
this.idle = true;
|
this.idle = true;
|
||||||
|
@ -45,69 +44,20 @@ define(
|
||||||
},
|
},
|
||||||
|
|
||||||
invokeCommand: function () {
|
invokeCommand: function () {
|
||||||
//TODO: Use Actioneer to handle icon swapping
|
|
||||||
|
|
||||||
var command = this.model.get('command');
|
var command = this.model.get('command');
|
||||||
if (command) {
|
if (command) {
|
||||||
this.idle = false;
|
this.idle = false;
|
||||||
this.$el.addClass('disabled');
|
|
||||||
this.ui.icon.addClass('icon-spinner icon-spin');
|
|
||||||
|
|
||||||
var self = this;
|
Actioneer.ExecuteCommand({
|
||||||
var commandPromise = CommandController.Execute(command);
|
command : command,
|
||||||
commandPromise.done(function () {
|
button : this.$el,
|
||||||
if (self.model.get('successMessage')) {
|
element : this.ui.icon,
|
||||||
Messenger.show({
|
errorMessage : this.model.get('errorMessage'),
|
||||||
message: self.model.get('successMessage')
|
successMessage: this.model.get('successMessage'),
|
||||||
|
always : this._commandAlways,
|
||||||
|
context : this
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.model.get('onSuccess')) {
|
|
||||||
if (!self.model.ownerContext) {
|
|
||||||
throw 'ownerContext must be set.';
|
|
||||||
}
|
|
||||||
|
|
||||||
self.model.get('onSuccess').call(self.model.ownerContext);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
invokeRoute: function () {
|
invokeRoute: function () {
|
||||||
|
@ -133,8 +83,13 @@ define(
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback.call(this.model.ownerContext);
|
callback.call(this.model.ownerContext);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_commandAlways: function () {
|
||||||
|
if (!this.isClosed) {
|
||||||
|
this.idle = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,8 @@ define(
|
||||||
this.left = options.left;
|
this.left = options.left;
|
||||||
this.right = options.right;
|
this.right = options.right;
|
||||||
this.toolbarContext = options.context;
|
this.toolbarContext = options.context;
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
onShow: function () {
|
onShow: function () {
|
||||||
if (this.left) {
|
if (this.left) {
|
||||||
_.each(this.left, this._showToolbarLeft, this);
|
_.each(this.left, this._showToolbarLeft, this);
|
||||||
|
@ -51,7 +49,6 @@ define(
|
||||||
this._showToolbar(element, index, 'right');
|
this._showToolbar(element, index, 'right');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
_showToolbar: function (buttonGroup, index, position) {
|
_showToolbar: function (buttonGroup, index, position) {
|
||||||
|
|
||||||
var groupCollection = new ButtonCollection();
|
var groupCollection = new ButtonCollection();
|
||||||
|
|
Loading…
Reference in New Issue