From f304ad50d1859c685ca847024cf4875742a96d67 Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Sat, 24 May 2014 12:48:55 +0200 Subject: [PATCH] New: Updated Nzbget Download Client proxy with time estimation for both download and post-processing stages. --- .../NzbgetTests/NzbgetFixture.cs | 26 +++- .../Checks/ImportMechanismCheckFixture.cs | 2 +- .../Clients/Nzbget/NzbGetQueueItem.cs | 4 +- .../Download/Clients/Nzbget/Nzbget.cs | 61 +++++++-- .../Clients/Nzbget/NzbgetBooleanResponse.cs | 10 -- .../Clients/Nzbget/NzbgetGlobalStatus.cs | 19 +++ .../Clients/Nzbget/NzbgetPostQueueItem.cs | 19 +++ .../Download/Clients/Nzbget/NzbgetProxy.cs | 30 ++++- ...zbgetListResponse.cs => NzbgetResponse.cs} | 6 +- .../Clients/Nzbget/VersionResponse.cs | 10 -- .../UsenetBlackhole/UsenetBlackhole.cs | 2 + .../Download/DownloadClientItem.cs | 21 +-- .../Download/DownloadTrackingService.cs | 121 +++++++++--------- src/NzbDrone.Core/NzbDrone.Core.csproj | 6 +- 14 files changed, 218 insertions(+), 119 deletions(-) delete mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetBooleanResponse.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetGlobalStatus.cs create mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPostQueueItem.cs rename src/NzbDrone.Core/Download/Clients/Nzbget/{NzbgetListResponse.cs => NzbgetResponse.cs} (57%) delete mode 100644 src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/NzbgetFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/NzbgetFixture.cs index e29186110..0dffee397 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/NzbgetFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/NzbgetTests/NzbgetFixture.cs @@ -52,7 +52,12 @@ public void Setup() Name = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE", DestDir = "somedirectory", Parameters = new List { new NzbgetParameter { Name = "drone", Value = "id" } }, - ParStatus = "Some Error" + ParStatus = "Some Error", + UnpackStatus = "NONE", + MoveStatus = "NONE", + ScriptStatus = "NONE", + DeleteStatus = "NONE", + MarkStatus = "NONE" }; _completed = new NzbgetHistoryItem @@ -63,8 +68,19 @@ public void Setup() DestDir = "somedirectory", Parameters = new List { new NzbgetParameter { Name = "drone", Value = "id" } }, ParStatus = "SUCCESS", - ScriptStatus = "NONE" + UnpackStatus = "NONE", + MoveStatus = "SUCCESS", + ScriptStatus = "NONE", + DeleteStatus = "NONE", + MarkStatus = "NONE" }; + + Mocker.GetMock() + .Setup(s => s.GetGlobalStatus(It.IsAny())) + .Returns(new NzbgetGlobalStatus + { + DownloadRate = 7000000 + }); } protected void WithFailedDownload() @@ -93,6 +109,10 @@ protected virtual void WithQueue(NzbgetQueueItem queue) Mocker.GetMock() .Setup(s => s.GetQueue(It.IsAny())) .Returns(list); + + Mocker.GetMock() + .Setup(s => s.GetPostQueue(It.IsAny())) + .Returns(new List()); } protected virtual void WithHistory(NzbgetHistoryItem history) @@ -134,7 +154,7 @@ public void queued_item_should_have_required_properties() [Test] public void paused_item_should_have_required_properties() { - _queued.PausedSizeLo = _queued.FileSizeLo; + _queued.PausedSizeLo = _queued.RemainingSizeLo; WithQueue(_queued); WithHistory(null); diff --git a/src/NzbDrone.Core.Test/HealthCheck/Checks/ImportMechanismCheckFixture.cs b/src/NzbDrone.Core.Test/HealthCheck/Checks/ImportMechanismCheckFixture.cs index 236470dc1..4e0724e84 100644 --- a/src/NzbDrone.Core.Test/HealthCheck/Checks/ImportMechanismCheckFixture.cs +++ b/src/NzbDrone.Core.Test/HealthCheck/Checks/ImportMechanismCheckFixture.cs @@ -44,7 +44,7 @@ private void GivenCompletedDownloadHandling(bool? enabled = null) Mocker.GetMock() .Setup(v => v.GetCompletedDownloads()) - .Returns(_completed.ToList()); + .Returns(_completed.ToArray()); } private void GivenDroneFactoryFolder(bool exists = false) diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs index 88b6c7b25..a951bd57d 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbGetQueueItem.cs @@ -8,7 +8,7 @@ public class NzbgetQueueItem public Int32 NzbId { get; set; } public Int32 FirstId { get; set; } public Int32 LastId { get; set; } - public string NzbName { get; set; } + public String NzbName { get; set; } public String Category { get; set; } public UInt32 FileSizeLo { get; set; } public UInt32 FileSizeHi { get; set; } @@ -16,6 +16,8 @@ public class NzbgetQueueItem public UInt32 RemainingSizeHi { get; set; } public UInt32 PausedSizeLo { get; set; } public UInt32 PausedSizeHi { get; set; } + public Int32 MinPriority { get; set; } + public Int32 MaxPriority { get; set; } public Int32 ActiveDownloads { get; set; } public List Parameters { get; set; } } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs index 828242bc9..bef490cf3 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs @@ -56,11 +56,15 @@ public override string Download(RemoteEpisode remoteEpisode) private IEnumerable GetQueue() { + NzbgetGlobalStatus globalStatus; List queue; + Dictionary postQueue; try { + globalStatus = _proxy.GetGlobalStatus(Settings); queue = _proxy.GetQueue(Settings); + postQueue = _proxy.GetPostQueue(Settings).ToDictionary(v => v.NzbId); } catch (DownloadClientException ex) { @@ -70,28 +74,57 @@ private IEnumerable GetQueue() var queueItems = new List(); + Int64 totalRemainingSize = 0; + foreach (var item in queue) { + var postQueueItem = postQueue.GetValueOrDefault(item.NzbId); + + Int64 totalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo); + Int64 pausedSize = MakeInt64(item.PausedSizeHi, item.PausedSizeLo); + Int64 remainingSize = MakeInt64(item.RemainingSizeHi, item.RemainingSizeLo); + var droneParameter = item.Parameters.SingleOrDefault(p => p.Name == "drone"); var queueItem = new DownloadClientItem(); queueItem.DownloadClientId = droneParameter == null ? item.NzbId.ToString() : droneParameter.Value.ToString(); queueItem.Title = item.NzbName; - queueItem.TotalSize = MakeInt64(item.FileSizeHi, item.FileSizeLo); - queueItem.RemainingSize = MakeInt64(item.RemainingSizeHi, item.RemainingSizeLo); + queueItem.TotalSize = totalSize; queueItem.Category = item.Category; - if (queueItem.TotalSize == MakeInt64(item.PausedSizeHi, item.PausedSizeLo)) + if (postQueueItem != null) + { + queueItem.Status = DownloadItemStatus.Downloading; + queueItem.Message = postQueueItem.ProgressLabel; + + if (postQueueItem.StageProgress != 0) + { + queueItem.RemainingTime = TimeSpan.FromSeconds(postQueueItem.StageTimeSec * 1000 / postQueueItem.StageProgress - postQueueItem.StageTimeSec); + } + } + else if (globalStatus.DownloadPaused || remainingSize == pausedSize) { queueItem.Status = DownloadItemStatus.Paused; - } - else if (item.ActiveDownloads == 0 && queueItem.RemainingSize != 0) - { - queueItem.Status = DownloadItemStatus.Queued; + queueItem.RemainingSize = remainingSize; } else { - queueItem.Status = DownloadItemStatus.Downloading; + if (item.ActiveDownloads == 0 && remainingSize != 0) + { + queueItem.Status = DownloadItemStatus.Queued; + } + else + { + queueItem.Status = DownloadItemStatus.Downloading; + } + + queueItem.RemainingSize = remainingSize - pausedSize; + + if (globalStatus.DownloadRate != 0) + { + queueItem.RemainingTime = TimeSpan.FromSeconds((totalRemainingSize + queueItem.RemainingSize) / globalStatus.DownloadRate); + totalRemainingSize += queueItem.RemainingSize; + } } queueItems.Add(queueItem); @@ -130,13 +163,17 @@ private IEnumerable GetHistory() historyItem.Category = item.Category; historyItem.Message = String.Format("PAR Status: {0} - Unpack Status: {1} - Move Status: {2} - Script Status: {3} - Delete Status: {4} - Mark Status: {5}", item.ParStatus, item.UnpackStatus, item.MoveStatus, item.ScriptStatus, item.DeleteStatus, item.MarkStatus); historyItem.Status = DownloadItemStatus.Completed; + historyItem.RemainingTime = TimeSpan.Zero; + + if (item.DeleteStatus == "MANUAL") + { + continue; + } if (!successStatus.Contains(item.ParStatus) || !successStatus.Contains(item.UnpackStatus) || !successStatus.Contains(item.MoveStatus) || - !successStatus.Contains(item.ScriptStatus) || - !successStatus.Contains(item.DeleteStatus) || - !successStatus.Contains(item.MarkStatus)) + !successStatus.Contains(item.ScriptStatus)) { historyItem.Status = DownloadItemStatus.Failed; } @@ -179,7 +216,7 @@ public override void Test() _proxy.GetVersion(Settings); } - private VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null) + private String GetVersion(string host = null, int port = 0, string username = null, string password = null) { return _proxy.GetVersion(Settings); } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetBooleanResponse.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetBooleanResponse.cs deleted file mode 100644 index 6c536ba7d..000000000 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetBooleanResponse.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace NzbDrone.Core.Download.Clients.Nzbget -{ - public class NzbgetBooleanResponse - { - public String Version { get; set; } - public Boolean Result { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetGlobalStatus.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetGlobalStatus.cs new file mode 100644 index 000000000..fcf5f6e46 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetGlobalStatus.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Download.Clients.Nzbget +{ + public class NzbgetGlobalStatus + { + public UInt32 RemainingSizeLo { get; set; } + public UInt32 RemainingSizeHi { get; set; } + public UInt32 DownloadedSizeLo { get; set; } + public UInt32 DownloadedSizeHi { get; set; } + public UInt32 DownloadRate { get; set; } + public UInt32 AverageDownloadRate { get; set; } + public UInt32 DownloadLimit { get; set; } + public Boolean DownloadPaused { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPostQueueItem.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPostQueueItem.cs new file mode 100644 index 000000000..450e07eab --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetPostQueueItem.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Download.Clients.Nzbget +{ + public class NzbgetPostQueueItem + { + public Int32 NzbId { get; set; } + public String NzbName { get; set; } + public String Stage { get; set; } + public String ProgressLabel { get; set; } + public Int32 FileProgress { get; set; } + public Int32 StageProgress { get; set; } + public Int32 TotalTimeSec { get; set; } + public Int32 StageTimeSec { get; set; } + } +} diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs index c1c176e4b..5d6e34bb6 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetProxy.cs @@ -13,9 +13,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget public interface INzbgetProxy { string DownloadNzb(Stream nzb, string title, string category, int priority, NzbgetSettings settings); + NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings); List GetQueue(NzbgetSettings settings); + List GetPostQueue(NzbgetSettings settings); List GetHistory(NzbgetSettings settings); - VersionResponse GetVersion(NzbgetSettings settings); + String GetVersion(NzbgetSettings settings); void RemoveFromHistory(string id, NzbgetSettings settings); void RetryDownload(string id, NzbgetSettings settings); } @@ -34,7 +36,7 @@ public string DownloadNzb(Stream nzb, string title, string category, int priorit var parameters = new object[] { title, category, priority, false, Convert.ToBase64String(nzb.ToBytes()) }; var request = BuildRequest(new JsonRequest("append", parameters)); - var response = Json.Deserialize(ProcessRequest(request, settings)); + var response = Json.Deserialize>(ProcessRequest(request, settings)); _logger.Debug("Queue Response: [{0}]", response.Result); if (!response.Result) @@ -61,25 +63,39 @@ public string DownloadNzb(Stream nzb, string title, string category, int priorit return droneId; } + public NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings) + { + var request = BuildRequest(new JsonRequest("status")); + + return Json.Deserialize>(ProcessRequest(request, settings)).Result; + } + public List GetQueue(NzbgetSettings settings) { var request = BuildRequest(new JsonRequest("listgroups")); - return Json.Deserialize>(ProcessRequest(request, settings)).QueueItems; + return Json.Deserialize>>(ProcessRequest(request, settings)).Result; + } + + public List GetPostQueue(NzbgetSettings settings) + { + var request = BuildRequest(new JsonRequest("postqueue")); + + return Json.Deserialize>>(ProcessRequest(request, settings)).Result; } public List GetHistory(NzbgetSettings settings) { var request = BuildRequest(new JsonRequest("history")); - return Json.Deserialize>(ProcessRequest(request, settings)).QueueItems; + return Json.Deserialize>>(ProcessRequest(request, settings)).Result; } - public VersionResponse GetVersion(NzbgetSettings settings) + public String GetVersion(NzbgetSettings settings) { var request = BuildRequest(new JsonRequest("version")); - return Json.Deserialize(ProcessRequest(request, settings)); + return Json.Deserialize>(ProcessRequest(request, settings)).Version; } public void RemoveFromHistory(string id, NzbgetSettings settings) @@ -120,7 +136,7 @@ private bool EditQueue(string command, int offset, string editText, int id, Nzbg { var parameters = new object[] { command, offset, editText, id }; var request = BuildRequest(new JsonRequest("editqueue", parameters)); - var response = Json.Deserialize(ProcessRequest(request, settings)); + var response = Json.Deserialize>(ProcessRequest(request, settings)); return response.Result; } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetListResponse.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetResponse.cs similarity index 57% rename from src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetListResponse.cs rename to src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetResponse.cs index bb51dbcc6..d13f53fa5 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetListResponse.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/NzbgetResponse.cs @@ -4,11 +4,11 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { - public class NzbgetListResponse + public class NzbgetResponse { public String Version { get; set; } - [JsonProperty(PropertyName = "result")] - public List QueueItems { get; set; } + public T Result { get; set; } + } } diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs deleted file mode 100644 index 780fd90ad..000000000 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/VersionResponse.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace NzbDrone.Core.Download.Clients.Nzbget -{ - public class VersionResponse - { - public String Version { get; set; } - public String Result { get; set; } - } -} diff --git a/src/NzbDrone.Core/Download/Clients/UsenetBlackhole/UsenetBlackhole.cs b/src/NzbDrone.Core/Download/Clients/UsenetBlackhole/UsenetBlackhole.cs index d534429ad..ec1865c2f 100644 --- a/src/NzbDrone.Core/Download/Clients/UsenetBlackhole/UsenetBlackhole.cs +++ b/src/NzbDrone.Core/Download/Clients/UsenetBlackhole/UsenetBlackhole.cs @@ -83,6 +83,8 @@ public override IEnumerable GetItems() else { historyItem.Status = DownloadItemStatus.Completed; + + historyItem.RemainingTime = TimeSpan.Zero; } historyItem.RemoteEpisode = GetRemoteEpisode(historyItem.Title); diff --git a/src/NzbDrone.Core/Download/DownloadClientItem.cs b/src/NzbDrone.Core/Download/DownloadClientItem.cs index e8b8b6fc5..6cc2dbb2f 100644 --- a/src/NzbDrone.Core/Download/DownloadClientItem.cs +++ b/src/NzbDrone.Core/Download/DownloadClientItem.cs @@ -8,22 +8,23 @@ namespace NzbDrone.Core.Download { public class DownloadClientItem { - public string DownloadClient { get; set; } - public string DownloadClientId { get; set; } - public string Category { get; set; } - public string Title { get; set; } + public String DownloadClient { get; set; } + public String DownloadClientId { get; set; } + public String Category { get; set; } + public String Title { get; set; } - public long TotalSize { get; set; } - public long RemainingSize { get; set; } + public Int64 TotalSize { get; set; } + public Int64 RemainingSize { get; set; } public TimeSpan DownloadTime { get; set; } public TimeSpan RemainingTime { get; set; } - public string OutputPath { get; set; } - public string Message { get; set; } + public String OutputPath { get; set; } + public String Message { get; set; } public DownloadItemStatus Status { get; set; } - public bool IsEncrypted { get; set; } - public bool IsReadOnly { get; set; } + public Boolean IsEncrypted { get; set; } + public Boolean IsReadOnly { get; set; } + public RemoteEpisode RemoteEpisode { get; set; } } } diff --git a/src/NzbDrone.Core/Download/DownloadTrackingService.cs b/src/NzbDrone.Core/Download/DownloadTrackingService.cs index d06017125..78bb5ec5f 100644 --- a/src/NzbDrone.Core/Download/DownloadTrackingService.cs +++ b/src/NzbDrone.Core/Download/DownloadTrackingService.cs @@ -15,12 +15,12 @@ namespace NzbDrone.Core.Download { public interface IDownloadTrackingService { - List GetTrackedDownloads(); - List GetCompletedDownloads(); - List GetQueuedDownloads(); + TrackedDownload[] GetTrackedDownloads(); + TrackedDownload[] GetCompletedDownloads(); + TrackedDownload[] GetQueuedDownloads(); } - public class DownloadTrackingService : IDownloadTrackingService, IExecute, IHandle + public class DownloadTrackingService : IDownloadTrackingService, IExecute, IHandle, IHandle { private readonly IProvideDownloadClient _downloadClientProvider; private readonly IHistoryService _historyService; @@ -30,8 +30,7 @@ public class DownloadTrackingService : IDownloadTrackingService, IExecute _trackedDownloads; - private readonly ICached> _queuedDownloads; + private readonly ICached _trackedDownloadCache; public static string DOWNLOAD_CLIENT = "downloadClient"; public static string DOWNLOAD_CLIENT_ID = "downloadClientId"; @@ -53,108 +52,105 @@ public DownloadTrackingService(IProvideDownloadClient downloadClientProvider, _completedDownloadService = completedDownloadService; _logger = logger; - _trackedDownloads = cacheManager.GetCache(GetType()); - _queuedDownloads = cacheManager.GetCache>(GetType(), "queued"); + _trackedDownloadCache = cacheManager.GetCache(GetType()); } - public List GetTrackedDownloads() + public TrackedDownload[] GetTrackedDownloads() { - return _trackedDownloads.Values.ToList(); + return _trackedDownloadCache.Get("tracked", () => new TrackedDownload[0]); } - public List GetCompletedDownloads() + public TrackedDownload[] GetCompletedDownloads() { - return _trackedDownloads.Values.Where(v => v.State == TrackedDownloadState.Downloading && v.DownloadItem.Status == DownloadItemStatus.Completed).ToList(); + return GetTrackedDownloads() + .Where(v => v.State == TrackedDownloadState.Downloading && v.DownloadItem.Status == DownloadItemStatus.Completed) + .ToArray(); } - public List GetQueuedDownloads() + public TrackedDownload[] GetQueuedDownloads() { - return _queuedDownloads.Get("queued", () => + return _trackedDownloadCache.Get("queued", () => { UpdateTrackedDownloads(); - var enabledFailedDownloadHandling = _configService.EnableFailedDownloadHandling; - var enabledCompletedDownloadHandling = _configService.EnableCompletedDownloadHandling; - - return _trackedDownloads.Values - .Where(v => v.State == TrackedDownloadState.Downloading) - .Where(v => - v.DownloadItem.Status == DownloadItemStatus.Queued || - v.DownloadItem.Status == DownloadItemStatus.Paused || - v.DownloadItem.Status == DownloadItemStatus.Downloading || - v.DownloadItem.Status == DownloadItemStatus.Failed && enabledFailedDownloadHandling || - v.DownloadItem.Status == DownloadItemStatus.Completed && enabledCompletedDownloadHandling) - .ToList(); + return FilterQueuedDownloads(GetTrackedDownloads()); }, TimeSpan.FromSeconds(5.0)); } - private TrackedDownload GetTrackedDownload(IDownloadClient downloadClient, DownloadClientItem queueItem) + private TrackedDownload[] FilterQueuedDownloads(IEnumerable trackedDownloads) { - var id = String.Format("{0}-{1}", downloadClient.Definition.Id, queueItem.DownloadClientId); - var trackedDownload = _trackedDownloads.Get(id, () => new TrackedDownload - { - TrackingId = id, - DownloadClient = downloadClient.Definition.Id, - StartedTracking = DateTime.UtcNow, - State = TrackedDownloadState.Unknown - }); + var enabledFailedDownloadHandling = _configService.EnableFailedDownloadHandling; + var enabledCompletedDownloadHandling = _configService.EnableCompletedDownloadHandling; - trackedDownload.DownloadItem = queueItem; - - return trackedDownload; + return trackedDownloads + .Where(v => v.State == TrackedDownloadState.Downloading) + .Where(v => + v.DownloadItem.Status == DownloadItemStatus.Queued || + v.DownloadItem.Status == DownloadItemStatus.Paused || + v.DownloadItem.Status == DownloadItemStatus.Downloading || + v.DownloadItem.Status == DownloadItemStatus.Failed && enabledFailedDownloadHandling || + v.DownloadItem.Status == DownloadItemStatus.Completed && enabledCompletedDownloadHandling) + .ToArray(); } - + private List GetHistoryItems(List grabbedHistory, string downloadClientId) { return grabbedHistory.Where(h => downloadClientId.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID))) .ToList(); } - private Boolean UpdateTrackedDownloads() { var downloadClients = _downloadClientProvider.GetDownloadClients(); - var oldTrackedDownloads = new HashSet(_trackedDownloads.Values); - var newTrackedDownloads = new HashSet(); + var oldTrackedDownloads = GetTrackedDownloads().ToDictionary(v => v.TrackingId); + var newTrackedDownloads = new List(); var stateChanged = false; foreach (var downloadClient in downloadClients) { - var downloadClientHistory = downloadClient.GetItems().Select(v => GetTrackedDownload(downloadClient, v)).ToList(); - foreach (var trackedDownload in downloadClientHistory) + var downloadClientHistory = downloadClient.GetItems().ToList(); + foreach (var downloadItem in downloadClientHistory) { - if (!oldTrackedDownloads.Contains(trackedDownload)) + var trackingId = String.Format("{0}-{1}", downloadClient.Definition.Id, downloadItem.DownloadClientId); + TrackedDownload trackedDownload; + + if (!oldTrackedDownloads.TryGetValue(trackingId, out trackedDownload)) { - _logger.Trace("Started tracking download from history: {0}", trackedDownload.TrackingId); + trackedDownload = new TrackedDownload + { + TrackingId = trackingId, + DownloadClient = downloadClient.Definition.Id, + StartedTracking = DateTime.UtcNow, + State = TrackedDownloadState.Unknown + }; + + _logger.Trace("Started tracking download from history: {0}: {1}", trackedDownload.TrackingId, downloadItem.Title); stateChanged = true; } + trackedDownload.DownloadItem = downloadItem; + newTrackedDownloads.Add(trackedDownload); } } - foreach (var item in oldTrackedDownloads.Except(newTrackedDownloads)) + foreach (var downloadItem in oldTrackedDownloads.Values.Except(newTrackedDownloads)) { - if (item.State != TrackedDownloadState.Removed) + if (downloadItem.State != TrackedDownloadState.Removed) { - item.State = TrackedDownloadState.Removed; + downloadItem.State = TrackedDownloadState.Removed; stateChanged = true; - _logger.Debug("Item removed from download client by user: {0}", item.TrackingId); + _logger.Debug("Item removed from download client by user: {0}: {1}", downloadItem.TrackingId, downloadItem.DownloadItem.Title); } + + _logger.Trace("Stopped tracking download: {0}: {1}", downloadItem.TrackingId, downloadItem.DownloadItem.Title); } - foreach (var item in newTrackedDownloads.Union(oldTrackedDownloads).Where(v => v.State == TrackedDownloadState.Removed)) - { - _trackedDownloads.Remove(item.TrackingId); - - _logger.Trace("Stopped tracking download: {0}", item.TrackingId); - } - - _queuedDownloads.Clear(); + _trackedDownloadCache.Set("tracked", newTrackedDownloads.ToArray()); return stateChanged; } @@ -168,7 +164,7 @@ private void ProcessTrackedDownloads() var stateChanged = UpdateTrackedDownloads(); var downloadClients = _downloadClientProvider.GetDownloadClients(); - var trackedDownloads = _trackedDownloads.Values.ToArray(); + var trackedDownloads = GetTrackedDownloads(); foreach (var trackedDownload in trackedDownloads) { @@ -190,6 +186,8 @@ private void ProcessTrackedDownloads() } } + _trackedDownloadCache.Set("queued", FilterQueuedDownloads(trackedDownloads), TimeSpan.FromSeconds(5.0)); + if (stateChanged) { _eventAggregator.PublishEvent(new UpdateQueueEvent()); @@ -205,5 +203,10 @@ public void Handle(ApplicationStartedEvent message) { ProcessTrackedDownloads(); } + + public void Handle(EpisodeGrabbedEvent message) + { + ProcessTrackedDownloads(); + } } } diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 38edae8a0..b46015936 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -239,6 +239,8 @@ + + @@ -525,13 +527,11 @@ - - + -