From 9d2fbddc7d7879c81cf58918afe1c377a551877f Mon Sep 17 00:00:00 2001 From: Qstick Date: Sat, 1 Sep 2018 23:11:19 -0400 Subject: [PATCH] New: Cancel tasks in command queue --- frontend/src/Store/Actions/commandActions.js | 1 + .../createCommandExecutingSelector.js | 3 ++- src/Lidarr.Api.V1/Commands/CommandModule.cs | 3 +-- .../Messaging/Commands/CommandQueue.cs | 18 ++++++++++++++++++ .../Messaging/Commands/CommandQueueManager.cs | 11 +++++++++++ 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/frontend/src/Store/Actions/commandActions.js b/frontend/src/Store/Actions/commandActions.js index e0dd81d3d..2122b72a2 100644 --- a/frontend/src/Store/Actions/commandActions.js +++ b/frontend/src/Store/Actions/commandActions.js @@ -176,6 +176,7 @@ export const actionHandlers = handleThunks({ } }); + dispatch(updateItem({ section: 'commands', ...payload })); scheduleRemoveCommand(payload, dispatch); showCommandMessage(payload, dispatch); } diff --git a/frontend/src/Store/Selectors/createCommandExecutingSelector.js b/frontend/src/Store/Selectors/createCommandExecutingSelector.js index 337b31f6a..c3beb9a4d 100644 --- a/frontend/src/Store/Selectors/createCommandExecutingSelector.js +++ b/frontend/src/Store/Selectors/createCommandExecutingSelector.js @@ -6,7 +6,8 @@ function createCommandExecutingSelector(name, contraints = {}) { return createSelector( createCommandsSelector(), (commands) => { - return isCommandExecuting(findCommand(commands, { name, ...contraints })); + const command = findCommand(commands, { name, ...contraints }); + return isCommandExecuting(command); } ); } diff --git a/src/Lidarr.Api.V1/Commands/CommandModule.cs b/src/Lidarr.Api.V1/Commands/CommandModule.cs index 088a52698..7f614f99e 100644 --- a/src/Lidarr.Api.V1/Commands/CommandModule.cs +++ b/src/Lidarr.Api.V1/Commands/CommandModule.cs @@ -68,8 +68,7 @@ namespace Lidarr.Api.V1.Commands private void CancelCommand(int id) { - // TODO: Cancel the existing command - // Executing tasks should preferably exit gracefully + _commandQueueManager.Cancel(id); } public void Handle(CommandUpdatedEvent message) diff --git a/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs b/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs index 793f1eb3a..b884e6bb0 100644 --- a/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs +++ b/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs @@ -71,6 +71,24 @@ namespace NzbDrone.Core.Messaging.Commands } } + public bool RemoveIfQueued(int id) + { + var rval = false; + + lock (_mutex) + { + var command = _items.FirstOrDefault(q => q.Id == id); + + if (command?.Status == CommandStatus.Queued) + { + _items.Remove(command); + rval = true; + } + } + + return rval; + } + public List QueuedOrStarted() { return All().Where(q => q.Status == CommandStatus.Queued || q.Status == CommandStatus.Started) diff --git a/src/NzbDrone.Core/Messaging/Commands/CommandQueueManager.cs b/src/NzbDrone.Core/Messaging/Commands/CommandQueueManager.cs index 590196dfa..ce9b3c5cc 100644 --- a/src/NzbDrone.Core/Messaging/Commands/CommandQueueManager.cs +++ b/src/NzbDrone.Core/Messaging/Commands/CommandQueueManager.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Threading; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.Serializer; using NzbDrone.Core.Lifecycle; +using NzbDrone.Core.Exceptions; using NzbDrone.Core.Messaging.Events; namespace NzbDrone.Core.Messaging.Commands @@ -25,6 +27,7 @@ namespace NzbDrone.Core.Messaging.Commands void Complete(CommandModel command, string message); void Fail(CommandModel command, string message, Exception e); void Requeue(); + void Cancel(int id); void CleanCommands(); } @@ -193,6 +196,14 @@ namespace NzbDrone.Core.Messaging.Commands } } + public void Cancel(int id) + { + if (!_commandQueue.RemoveIfQueued(id)) + { + throw new NzbDroneClientException(HttpStatusCode.Conflict, "Unable to cancel task"); + } + } + public void CleanCommands() { _logger.Trace("Cleaning up old commands");