diff --git a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs index 75299e6c5..56f1b7a45 100644 --- a/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs +++ b/src/NzbDrone.Core/Download/Pending/PendingReleaseService.cs @@ -311,11 +311,11 @@ namespace NzbDrone.Core.Download.Pending ect = ect.AddMinutes(_configService.RssSyncInterval); } - var timeleft = ect.Subtract(DateTime.UtcNow); + var timeLeft = ect.Subtract(DateTime.UtcNow); - if (timeleft.TotalSeconds < 0) + if (timeLeft.TotalSeconds < 0) { - timeleft = TimeSpan.Zero; + timeLeft = TimeSpan.Zero; } string downloadClientName = null; @@ -336,9 +336,9 @@ namespace NzbDrone.Core.Download.Pending Languages = pendingRelease.RemoteMovie.Languages, Title = pendingRelease.Title, Size = pendingRelease.RemoteMovie.Release.Size, - Sizeleft = pendingRelease.RemoteMovie.Release.Size, + SizeLeft = pendingRelease.RemoteMovie.Release.Size, RemoteMovie = pendingRelease.RemoteMovie, - Timeleft = timeleft, + TimeLeft = timeLeft, EstimatedCompletionTime = ect, Added = pendingRelease.Added, Status = Enum.TryParse(pendingRelease.Reason.ToString(), out QueueStatus outValue) ? outValue : QueueStatus.Unknown, diff --git a/src/NzbDrone.Core/Queue/Queue.cs b/src/NzbDrone.Core/Queue/Queue.cs index acfd7bbd9..aba9f5704 100644 --- a/src/NzbDrone.Core/Queue/Queue.cs +++ b/src/NzbDrone.Core/Queue/Queue.cs @@ -17,8 +17,8 @@ namespace NzbDrone.Core.Queue public QualityModel Quality { get; set; } public decimal Size { get; set; } public string Title { get; set; } - public decimal Sizeleft { get; set; } - public TimeSpan? Timeleft { get; set; } + public decimal SizeLeft { get; set; } + public TimeSpan? TimeLeft { get; set; } public DateTime? EstimatedCompletionTime { get; set; } public DateTime? Added { get; set; } public QueueStatus Status { get; set; } diff --git a/src/NzbDrone.Core/Queue/QueueService.cs b/src/NzbDrone.Core/Queue/QueueService.cs index 92ec87237..e4607b943 100644 --- a/src/NzbDrone.Core/Queue/QueueService.cs +++ b/src/NzbDrone.Core/Queue/QueueService.cs @@ -62,8 +62,8 @@ namespace NzbDrone.Core.Queue Quality = trackedDownload.RemoteMovie?.ParsedMovieInfo.Quality ?? new QualityModel(Quality.Unknown), Title = trackedDownload.DownloadItem.Title, Size = trackedDownload.DownloadItem.TotalSize, - Sizeleft = trackedDownload.DownloadItem.RemainingSize, - Timeleft = trackedDownload.DownloadItem.RemainingTime, + SizeLeft = trackedDownload.DownloadItem.RemainingSize, + TimeLeft = trackedDownload.DownloadItem.RemainingTime, Status = Enum.TryParse(trackedDownload.DownloadItem.Status.ToString(), out QueueStatus outValue) ? outValue : QueueStatus.Unknown, TrackedDownloadStatus = trackedDownload.Status, TrackedDownloadState = trackedDownload.State, @@ -82,9 +82,9 @@ namespace NzbDrone.Core.Queue queue.Id = HashConverter.GetHashInt31($"trackedDownload-{trackedDownload.DownloadClient}-{trackedDownload.DownloadItem.DownloadId}"); - if (queue.Timeleft.HasValue) + if (queue.TimeLeft.HasValue) { - queue.EstimatedCompletionTime = DateTime.UtcNow.Add(queue.Timeleft.Value); + queue.EstimatedCompletionTime = DateTime.UtcNow.Add(queue.TimeLeft.Value); } return queue; diff --git a/src/NzbDrone.Integration.Test/ApiTests/QueueFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/QueueFixture.cs new file mode 100644 index 000000000..e659ca5b1 --- /dev/null +++ b/src/NzbDrone.Integration.Test/ApiTests/QueueFixture.cs @@ -0,0 +1,73 @@ +using System.IO; +using System.Linq; +using System.Threading; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Messaging.Commands; +using NzbDrone.Integration.Test.Client; +using Radarr.Api.V3.Queue; +using Radarr.Http; + +namespace NzbDrone.Integration.Test.ApiTests +{ + [TestFixture] + public class QueueFixture : IntegrationTest + { + private PagingResource GetFirstPage() + { + var request = Queue.BuildRequest(); + request.AddParameter("includeUnknownMovieItems", true); + + return Queue.Get>(request); + } + + private void RefreshQueue() + { + var command = Commands.Post(new SimpleCommandResource { Name = "RefreshMonitoredDownloads" }); + + for (var i = 0; i < 30; i++) + { + var updatedCommand = Commands.Get(command.Id); + + if (updatedCommand.Status == CommandStatus.Completed) + { + return; + } + + Thread.Sleep(1000); + i++; + } + } + + [Test] + [Order(0)] + public void ensure_queue_is_empty_when_download_client_is_configured() + { + EnsureNoDownloadClient(); + EnsureDownloadClient(); + + var queue = GetFirstPage(); + + queue.TotalRecords.Should().Be(0); + queue.Records.Should().BeEmpty(); + } + + [Test] + [Order(1)] + public void ensure_queue_is_not_empty() + { + EnsureNoDownloadClient(); + + var client = EnsureDownloadClient(); + var directory = client.Fields.First(v => v.Name == "watchFolder").Value as string; + + File.WriteAllText(Path.Combine(directory, "Movie.Title.2024.mkv"), "Test Download"); + RefreshQueue(); + + var queue = GetFirstPage(); + + queue.TotalRecords.Should().Be(1); + queue.Records.Should().NotBeEmpty(); + } + } +} diff --git a/src/NzbDrone.Integration.Test/Client/QueueClient.cs b/src/NzbDrone.Integration.Test/Client/QueueClient.cs new file mode 100644 index 000000000..bc669d290 --- /dev/null +++ b/src/NzbDrone.Integration.Test/Client/QueueClient.cs @@ -0,0 +1,13 @@ +using Radarr.Api.V3.Queue; +using RestSharp; + +namespace NzbDrone.Integration.Test.Client +{ + public class QueueClient : ClientBase + { + public QueueClient(IRestClient restClient, string apiKey) + : base(restClient, apiKey) + { + } + } +} diff --git a/src/NzbDrone.Integration.Test/IntegrationTestBase.cs b/src/NzbDrone.Integration.Test/IntegrationTestBase.cs index 517fa27d2..4ba8e7391 100644 --- a/src/NzbDrone.Integration.Test/IntegrationTestBase.cs +++ b/src/NzbDrone.Integration.Test/IntegrationTestBase.cs @@ -53,6 +53,7 @@ namespace NzbDrone.Integration.Test public ClientBase Tags; public ClientBase WantedMissing; public ClientBase WantedCutoffUnmet; + public QueueClient Queue; private List _signalRReceived; @@ -115,6 +116,7 @@ namespace NzbDrone.Integration.Test Tags = new ClientBase(RestClient, ApiKey); WantedMissing = new ClientBase(RestClient, ApiKey, "wanted/missing"); WantedCutoffUnmet = new ClientBase(RestClient, ApiKey, "wanted/cutoff"); + Queue = new QueueClient(RestClient, ApiKey); } [OneTimeTearDown] diff --git a/src/Radarr.Api.V3/Queue/QueueController.cs b/src/Radarr.Api.V3/Queue/QueueController.cs index 0b506fea4..00095ed13 100644 --- a/src/Radarr.Api.V3/Queue/QueueController.cs +++ b/src/Radarr.Api.V3/Queue/QueueController.cs @@ -214,8 +214,8 @@ namespace Radarr.Api.V3.Queue if (pagingSpec.SortKey == "timeleft") { ordered = ascending - ? fullQueue.OrderBy(q => q.Timeleft, new TimeleftComparer()) - : fullQueue.OrderByDescending(q => q.Timeleft, new TimeleftComparer()); + ? fullQueue.OrderBy(q => q.TimeLeft, new TimeleftComparer()) + : fullQueue.OrderByDescending(q => q.TimeLeft, new TimeleftComparer()); } else if (pagingSpec.SortKey == "estimatedCompletionTime") { @@ -266,7 +266,7 @@ namespace Radarr.Api.V3.Queue ordered = ascending ? fullQueue.OrderBy(orderByFunc) : fullQueue.OrderByDescending(orderByFunc); } - ordered = ordered.ThenByDescending(q => q.Size == 0 ? 0 : 100 - (q.Sizeleft / q.Size * 100)); + ordered = ordered.ThenByDescending(q => q.Size == 0 ? 0 : 100 - (q.SizeLeft / q.Size * 100)); pagingSpec.Records = ordered.Skip((pagingSpec.Page - 1) * pagingSpec.PageSize).Take(pagingSpec.PageSize).ToList(); pagingSpec.TotalRecords = fullQueue.Count; @@ -300,9 +300,9 @@ namespace Radarr.Api.V3.Queue return q => q.Size; case "progress": // Avoid exploding if a download's size is 0 - return q => 100 - (q.Sizeleft / Math.Max(q.Size * 100, 1)); + return q => 100 - (q.SizeLeft / Math.Max(q.Size * 100, 1)); default: - return q => q.Timeleft; + return q => q.TimeLeft; } } diff --git a/src/Radarr.Api.V3/Queue/QueueResource.cs b/src/Radarr.Api.V3/Queue/QueueResource.cs index e3826396b..e28b896a4 100644 --- a/src/Radarr.Api.V3/Queue/QueueResource.cs +++ b/src/Radarr.Api.V3/Queue/QueueResource.cs @@ -22,8 +22,11 @@ namespace Radarr.Api.V3.Queue public int CustomFormatScore { get; set; } public decimal Size { get; set; } public string Title { get; set; } - public decimal Sizeleft { get; set; } - public TimeSpan? Timeleft { get; set; } + + // Collides with existing properties due to case-insensitive deserialization + // public decimal SizeLeft { get; set; } + // public TimeSpan? TimeLeft { get; set; } + public DateTime? EstimatedCompletionTime { get; set; } public DateTime? Added { get; set; } public QueueStatus Status { get; set; } @@ -37,6 +40,12 @@ namespace Radarr.Api.V3.Queue public bool DownloadClientHasPostImportCategory { get; set; } public string Indexer { get; set; } public string OutputPath { get; set; } + + [Obsolete("Will be replaced by SizeLeft")] + public decimal Sizeleft { get; set; } + + [Obsolete("Will be replaced by TimeLeft")] + public TimeSpan? Timeleft { get; set; } } public static class QueueResourceMapper @@ -62,8 +71,11 @@ namespace Radarr.Api.V3.Queue CustomFormatScore = customFormatScore, Size = model.Size, Title = model.Title, - Sizeleft = model.Sizeleft, - Timeleft = model.Timeleft, + + // Collides with existing properties due to case-insensitive deserialization + // SizeLeft = model.SizeLeft, + // TimeLeft = model.TimeLeft, + EstimatedCompletionTime = model.EstimatedCompletionTime, Added = model.Added, Status = model.Status, @@ -76,7 +88,12 @@ namespace Radarr.Api.V3.Queue DownloadClient = model.DownloadClient, DownloadClientHasPostImportCategory = model.DownloadClientHasPostImportCategory, Indexer = model.Indexer, - OutputPath = model.OutputPath + OutputPath = model.OutputPath, + + #pragma warning disable CS0618 + Sizeleft = model.SizeLeft, + Timeleft = model.TimeLeft, + #pragma warning restore CS0618 }; }