mirror of https://github.com/lidarr/Lidarr
New: Don't Execute Certain Command Types In Parallel (#855)
This commit is contained in:
parent
b4fc4e88a5
commit
659844eeba
|
@ -0,0 +1,175 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using Moq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using NzbDrone.Core.ImportLists;
|
||||
using NzbDrone.Core.Update.Commands;
|
||||
using NzbDrone.Core.Music.Commands;
|
||||
|
||||
namespace NzbDrone.Core.Test.Messaging.Commands
|
||||
{
|
||||
[TestFixture]
|
||||
public class CommandQueueFixture : CoreTest<CommandQueue>
|
||||
{
|
||||
private void GivenStartedDiskCommand()
|
||||
{
|
||||
var commandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "CheckForFinishedDownload")
|
||||
.With(c => c.Body = new CheckForFinishedDownloadCommand())
|
||||
.With(c => c.Status = CommandStatus.Started)
|
||||
.Build();
|
||||
|
||||
Subject.Add(commandModel);
|
||||
}
|
||||
|
||||
private void GivenStartedTypeExclusiveCommand()
|
||||
{
|
||||
var commandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "ImportListSync")
|
||||
.With(c => c.Body = new ImportListSyncCommand())
|
||||
.With(c => c.Status = CommandStatus.Started)
|
||||
.Build();
|
||||
|
||||
Subject.Add(commandModel);
|
||||
}
|
||||
|
||||
private void GivenStartedExclusiveCommand()
|
||||
{
|
||||
var commandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "ApplicationUpdate")
|
||||
.With(c => c.Body = new ApplicationUpdateCommand())
|
||||
.With(c => c.Status = CommandStatus.Started)
|
||||
.Build();
|
||||
|
||||
Subject.Add(commandModel);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_return_disk_access_command_if_another_running()
|
||||
{
|
||||
GivenStartedDiskCommand();
|
||||
|
||||
var newCommandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "CheckForFinishedDownload")
|
||||
.With(c => c.Body = new CheckForFinishedDownloadCommand())
|
||||
.Build();
|
||||
|
||||
Subject.Add(newCommandModel);
|
||||
|
||||
Subject.TryGet(out var command);
|
||||
|
||||
command.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_return_type_exclusive_command_if_another_running()
|
||||
{
|
||||
GivenStartedTypeExclusiveCommand();
|
||||
|
||||
var newCommandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "ImportListSync")
|
||||
.With(c => c.Body = new ImportListSyncCommand())
|
||||
.Build();
|
||||
|
||||
Subject.Add(newCommandModel);
|
||||
|
||||
Subject.TryGet(out var command);
|
||||
|
||||
command.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_type_exclusive_command_if_another_not_running()
|
||||
{
|
||||
GivenStartedDiskCommand();
|
||||
|
||||
var newCommandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "ImportListSync")
|
||||
.With(c => c.Body = new ImportListSyncCommand())
|
||||
.Build();
|
||||
|
||||
Subject.Add(newCommandModel);
|
||||
|
||||
Subject.TryGet(out var command);
|
||||
|
||||
command.Should().NotBeNull();
|
||||
command.Status.Should().Be(CommandStatus.Started);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_regular_command_if_type_exclusive_command_running()
|
||||
{
|
||||
GivenStartedTypeExclusiveCommand();
|
||||
|
||||
var newCommandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "RefreshArtist")
|
||||
.With(c => c.Body = new RefreshArtistCommand())
|
||||
.Build();
|
||||
|
||||
Subject.Add(newCommandModel);
|
||||
|
||||
Subject.TryGet(out var command);
|
||||
|
||||
command.Should().NotBeNull();
|
||||
command.Status.Should().Be(CommandStatus.Started);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_return_exclusive_command_if_any_running()
|
||||
{
|
||||
GivenStartedDiskCommand();
|
||||
|
||||
var newCommandModel = Builder<CommandModel>
|
||||
.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_any_command_if_exclusive_running()
|
||||
{
|
||||
GivenStartedExclusiveCommand();
|
||||
|
||||
var newCommandModel = Builder<CommandModel>
|
||||
.CreateNew()
|
||||
.With(c => c.Name = "RefreshArtist")
|
||||
.With(c => c.Body = new RefreshArtistCommand())
|
||||
.Build();
|
||||
|
||||
Subject.Add(newCommandModel);
|
||||
|
||||
Subject.TryGet(out var command);
|
||||
|
||||
command.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_null_if_nothing_queued()
|
||||
{
|
||||
GivenStartedDiskCommand();
|
||||
|
||||
Subject.TryGet(out var command);
|
||||
|
||||
command.Should().BeNull();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -265,6 +265,7 @@
|
|||
<Compile Include="MediaFiles\TrackImport\Specifications\UpgradeSpecificationFixture.cs" />
|
||||
<Compile Include="MediaFiles\ImportApprovedTracksFixture.cs" />
|
||||
<Compile Include="MediaFiles\MediaFileRepositoryFixture.cs" />
|
||||
<Compile Include="Messaging\Commands\CommandQueueFixture.cs" />
|
||||
<Compile Include="Messaging\Commands\CommandQueueManagerFixture.cs" />
|
||||
<Compile Include="MetadataSource\MetadataRequestBuilderFixture.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\SkyHookProxySearchFixture.cs" />
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace NzbDrone.Core.ImportLists
|
|||
|
||||
public override bool SendUpdatesToClient => true;
|
||||
|
||||
public override bool IsTypeExclusive => true;
|
||||
|
||||
public override bool UpdateScheduledTask => !DefinitionId.HasValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ namespace NzbDrone.Core.Messaging.Commands
|
|||
public virtual bool RequiresDiskAccess => false;
|
||||
public virtual bool IsExclusive => false;
|
||||
|
||||
public virtual bool IsTypeExclusive => false;
|
||||
|
||||
public string Name { get; private set; }
|
||||
public DateTime? LastExecutionTime { get; set; }
|
||||
public CommandTrigger Trigger { get; set; }
|
||||
|
|
|
@ -130,7 +130,11 @@ namespace NzbDrone.Core.Messaging.Commands
|
|||
var startedCommands = _items.Where(c => c.Status == CommandStatus.Started)
|
||||
.ToList();
|
||||
|
||||
var localItem = _items.Where(c =>
|
||||
var exclusiveTypes = startedCommands.Where(x => x.Body.IsTypeExclusive)
|
||||
.Select(x => x.Body.Name)
|
||||
.ToList();
|
||||
|
||||
var localItem = _items.Where(c =>
|
||||
{
|
||||
// If an executing command requires disk access don't return a command that
|
||||
// requires disk access. A lower priority or later queued task could be returned
|
||||
|
@ -141,6 +145,11 @@ namespace NzbDrone.Core.Messaging.Commands
|
|||
!c.Body.RequiresDiskAccess;
|
||||
}
|
||||
|
||||
// If an executing command is TypeExclusive don't return a command with same type
|
||||
if (startedCommands.Any(x => x.Body.IsTypeExclusive)) {
|
||||
return c.Status == CommandStatus.Queued && !exclusiveTypes.Any(x => x == c.Body.Name);
|
||||
}
|
||||
|
||||
return c.Status == CommandStatus.Queued;
|
||||
})
|
||||
.OrderByDescending(c => c.Priority)
|
||||
|
|
Loading…
Reference in New Issue