From 93cce9a02ef065ca45179f940d47974814e12be1 Mon Sep 17 00:00:00 2001 From: Qstick Date: Sat, 14 Jan 2023 17:52:11 -0600 Subject: [PATCH] Don't block task queue for queued update task when long running tasks queued Fixes #2935 Co-Authored-By: Mark McDowall --- .../Messaging/Commands/CommandQueueFixture.cs | 31 +++++++++++++++++++ .../ProcessMonitoredDownloadsCommand.cs | 2 ++ src/NzbDrone.Core/Indexers/RssSyncCommand.cs | 2 ++ .../Messaging/Commands/Command.cs | 2 +- .../Messaging/Commands/CommandQueue.cs | 13 +++++--- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/NzbDrone.Core.Test/Messaging/Commands/CommandQueueFixture.cs b/src/NzbDrone.Core.Test/Messaging/Commands/CommandQueueFixture.cs index e7598a914..e044b3630 100644 --- a/src/NzbDrone.Core.Test/Messaging/Commands/CommandQueueFixture.cs +++ b/src/NzbDrone.Core.Test/Messaging/Commands/CommandQueueFixture.cs @@ -3,6 +3,7 @@ using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Download; using NzbDrone.Core.ImportLists; +using NzbDrone.Core.Indexers; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Music.Commands; using NzbDrone.Core.Test.Framework; @@ -25,6 +26,18 @@ namespace NzbDrone.Core.Test.Messaging.Commands Subject.Add(commandModel); } + private void GivenLongRunningCommand() + { + var commandModel = Builder + .CreateNew() + .With(c => c.Name = "RssSync") + .With(c => c.Body = new RssSyncCommand()) + .With(c => c.Status = CommandStatus.Started) + .Build(); + + Subject.Add(commandModel); + } + private void GivenStartedTypeExclusiveCommand() { var commandModel = Builder @@ -85,6 +98,24 @@ namespace NzbDrone.Core.Test.Messaging.Commands command.Should().BeNull(); } + [Test] + public void should_not_return_exclusive_command_if_long_running_command_running() + { + GivenLongRunningCommand(); + + var newCommandModel = Builder + .CreateNew() + .With(c => c.Name = "ApplicationUpdate") + .With(c => c.Body = new ApplicationUpdateCommand()) + .Build(); + + Subject.Add(newCommandModel); + + Subject.TryGet(out var command); + + command.Should().BeNull(); + } + [Test] public void should_not_return_type_exclusive_command_if_another_and_disk_access_command_running() { diff --git a/src/NzbDrone.Core/Download/ProcessMonitoredDownloadsCommand.cs b/src/NzbDrone.Core/Download/ProcessMonitoredDownloadsCommand.cs index c3c934031..4b39f1347 100644 --- a/src/NzbDrone.Core/Download/ProcessMonitoredDownloadsCommand.cs +++ b/src/NzbDrone.Core/Download/ProcessMonitoredDownloadsCommand.cs @@ -5,5 +5,7 @@ namespace NzbDrone.Core.Download public class ProcessMonitoredDownloadsCommand : Command { public override bool RequiresDiskAccess => true; + + public override bool IsLongRunning => true; } } diff --git a/src/NzbDrone.Core/Indexers/RssSyncCommand.cs b/src/NzbDrone.Core/Indexers/RssSyncCommand.cs index 47b9cca67..519e61f01 100644 --- a/src/NzbDrone.Core/Indexers/RssSyncCommand.cs +++ b/src/NzbDrone.Core/Indexers/RssSyncCommand.cs @@ -5,5 +5,7 @@ namespace NzbDrone.Core.Indexers public class RssSyncCommand : Command { public override bool SendUpdatesToClient => true; + + public override bool IsLongRunning => true; } } diff --git a/src/NzbDrone.Core/Messaging/Commands/Command.cs b/src/NzbDrone.Core/Messaging/Commands/Command.cs index c3fd74616..057c8d4c4 100644 --- a/src/NzbDrone.Core/Messaging/Commands/Command.cs +++ b/src/NzbDrone.Core/Messaging/Commands/Command.cs @@ -26,8 +26,8 @@ namespace NzbDrone.Core.Messaging.Commands public virtual string CompletionMessage => "Completed"; public virtual bool RequiresDiskAccess => false; public virtual bool IsExclusive => false; - public virtual bool IsTypeExclusive => false; + public virtual bool IsLongRunning => false; public string Name { get; private set; } public DateTime? LastExecutionTime { get; set; } diff --git a/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs b/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs index ae92ca94e..8b1b1077e 100644 --- a/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs +++ b/src/NzbDrone.Core/Messaging/Commands/CommandQueue.cs @@ -98,7 +98,7 @@ namespace NzbDrone.Core.Messaging.Commands public List QueuedOrStarted() { return All().Where(q => q.Status == CommandStatus.Queued || q.Status == CommandStatus.Started) - .ToList(); + .ToList(); } public IEnumerable GetConsumingEnumerable() @@ -158,7 +158,7 @@ namespace NzbDrone.Core.Messaging.Commands else { var startedCommands = _items.Where(c => c.Status == CommandStatus.Started) - .ToList(); + .ToList(); var exclusiveTypes = startedCommands.Where(x => x.Body.IsTypeExclusive) .Select(x => x.Body.Name) @@ -176,9 +176,14 @@ namespace NzbDrone.Core.Messaging.Commands queuedCommands = queuedCommands.Where(c => !exclusiveTypes.Any(x => x == c.Body.Name)); } + if (startedCommands.Any(x => x.Body.IsLongRunning)) + { + queuedCommands = queuedCommands.Where(c => c.Status == CommandStatus.Queued && !c.Body.IsExclusive); + } + var localItem = queuedCommands.OrderByDescending(c => c.Priority) - .ThenBy(c => c.QueuedAt) - .FirstOrDefault(); + .ThenBy(c => c.QueuedAt) + .FirstOrDefault(); // Nothing queued that meets the requirements if (localItem == null)