mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
Failed downloads are added to history
This commit is contained in:
parent
2e1b921543
commit
e64d2f33d6
198
src/NzbDrone.Core.Test/Download/FailedDownloadServiceFixture.cs
Normal file
198
src/NzbDrone.Core.Test/Download/FailedDownloadServiceFixture.cs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.History;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Download
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class FailedDownloadServiceFixture : CoreTest<FailedDownloadService>
|
||||||
|
{
|
||||||
|
private Series _series;
|
||||||
|
private Episode _episode;
|
||||||
|
private List<HistoryItem> _completed;
|
||||||
|
private List<HistoryItem> _failed;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_series = Builder<Series>.CreateNew().Build();
|
||||||
|
_episode = Builder<Episode>.CreateNew().Build();
|
||||||
|
|
||||||
|
_completed = Builder<HistoryItem>.CreateListOfSize(5)
|
||||||
|
.All()
|
||||||
|
.With(h => h.Status = HistoryStatus.Completed)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
_failed = Builder<HistoryItem>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(h => h.Status = HistoryStatus.Failed)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Mocker.GetMock<IProvideDownloadClient>()
|
||||||
|
.Setup(c => c.GetDownloadClient()).Returns(Mocker.GetMock<IDownloadClient>().Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenNoRecentHistory()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Setup(s => s.BetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), HistoryEventType.Grabbed))
|
||||||
|
.Returns(new List<History.History>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenRecentHistory(List<History.History> history)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Setup(s => s.BetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), HistoryEventType.Grabbed))
|
||||||
|
.Returns(history);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenNoFailedHistory()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Setup(s => s.Failed())
|
||||||
|
.Returns(new List<History.History>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenFailedHistory(List<History.History> failedHistory)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Setup(s => s.Failed())
|
||||||
|
.Returns(failedHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenFailedDownloadClientHistory()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IDownloadClient>()
|
||||||
|
.Setup(s => s.GetHistory(0, 20))
|
||||||
|
.Returns(_failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifyNoFailedDownloads()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IEventAggregator>()
|
||||||
|
.Verify(v => v.PublishEvent(It.IsAny<DownloadFailedEvent>()), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifyFailedDownloads(int count = 1)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IEventAggregator>()
|
||||||
|
.Verify(v => v.PublishEvent(It.IsAny<DownloadFailedEvent>()), Times.Exactly(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_process_if_no_download_client_history()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IDownloadClient>()
|
||||||
|
.Setup(s => s.GetHistory(0, 20))
|
||||||
|
.Returns(new List<HistoryItem>());
|
||||||
|
|
||||||
|
Subject.Execute(new FailedDownloadCommand());
|
||||||
|
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Verify(s => s.BetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), HistoryEventType.Grabbed),
|
||||||
|
Times.Never());
|
||||||
|
|
||||||
|
VerifyNoFailedDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_process_if_no_failed_items_in_download_client_history()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IDownloadClient>()
|
||||||
|
.Setup(s => s.GetHistory(0, 20))
|
||||||
|
.Returns(_completed);
|
||||||
|
|
||||||
|
Subject.Execute(new FailedDownloadCommand());
|
||||||
|
|
||||||
|
Mocker.GetMock<IHistoryService>()
|
||||||
|
.Verify(s => s.BetweenDates(It.IsAny<DateTime>(), It.IsAny<DateTime>(), HistoryEventType.Grabbed),
|
||||||
|
Times.Never());
|
||||||
|
|
||||||
|
VerifyNoFailedDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_process_if_matching_history_is_not_found()
|
||||||
|
{
|
||||||
|
GivenNoRecentHistory();
|
||||||
|
GivenFailedDownloadClientHistory();
|
||||||
|
|
||||||
|
Subject.Execute(new FailedDownloadCommand());
|
||||||
|
|
||||||
|
VerifyNoFailedDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_process_if_already_added_to_history_as_failed()
|
||||||
|
{
|
||||||
|
GivenFailedDownloadClientHistory();
|
||||||
|
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(1)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
GivenRecentHistory(history);
|
||||||
|
GivenFailedHistory(history);
|
||||||
|
|
||||||
|
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||||
|
history.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||||
|
|
||||||
|
Subject.Execute(new FailedDownloadCommand());
|
||||||
|
|
||||||
|
VerifyNoFailedDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_process_if_not_already_in_failed_history()
|
||||||
|
{
|
||||||
|
GivenFailedDownloadClientHistory();
|
||||||
|
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(1)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
GivenRecentHistory(history);
|
||||||
|
GivenNoFailedHistory();
|
||||||
|
|
||||||
|
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||||
|
history.First().Data.Add("downloadClientId", _failed.First().Id);
|
||||||
|
|
||||||
|
Subject.Execute(new FailedDownloadCommand());
|
||||||
|
|
||||||
|
VerifyFailedDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_process_for_each_failed_episode()
|
||||||
|
{
|
||||||
|
GivenFailedDownloadClientHistory();
|
||||||
|
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(2)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
GivenRecentHistory(history);
|
||||||
|
GivenNoFailedHistory();
|
||||||
|
|
||||||
|
history.ForEach(h =>
|
||||||
|
{
|
||||||
|
h.Data.Add("downloadClient", "SabnzbdClient");
|
||||||
|
h.Data.Add("downloadClientId", _failed.First().Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
Subject.Execute(new FailedDownloadCommand());
|
||||||
|
|
||||||
|
VerifyFailedDownloads(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -124,6 +124,7 @@
|
|||||||
<Compile Include="Download\DownloadClientTests\SabProviderTests\QueueFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\SabProviderTests\QueueFixture.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" />
|
||||||
<Compile Include="Download\DownloadServiceFixture.cs" />
|
<Compile Include="Download\DownloadServiceFixture.cs" />
|
||||||
|
<Compile Include="Download\FailedDownloadServiceFixture.cs" />
|
||||||
<Compile Include="Framework\CoreTest.cs" />
|
<Compile Include="Framework\CoreTest.cs" />
|
||||||
<Compile Include="Framework\DbTest.cs" />
|
<Compile Include="Framework\DbTest.cs" />
|
||||||
<Compile Include="Framework\NBuilderExtensions.cs" />
|
<Compile Include="Framework\NBuilderExtensions.cs" />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
@ -51,5 +52,10 @@ public IEnumerable<QueueItem> GetQueue()
|
|||||||
{
|
{
|
||||||
return new QueueItem[0];
|
return new QueueItem[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||||
|
{
|
||||||
|
return new HistoryItem[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,11 @@ public virtual IEnumerable<QueueItem> GetQueue()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||||
|
{
|
||||||
|
return new HistoryItem[0];
|
||||||
|
}
|
||||||
|
|
||||||
public virtual VersionModel GetVersion(string host = null, int port = 0, string username = null, string password = null)
|
public virtual VersionModel GetVersion(string host = null, int port = 0, string username = null, string password = null)
|
||||||
{
|
{
|
||||||
//Get saved values if any of these are defaults
|
//Get saved values if any of these are defaults
|
||||||
|
@ -65,6 +65,11 @@ public IEnumerable<QueueItem> GetQueue()
|
|||||||
return new QueueItem[0];
|
return new QueueItem[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||||
|
{
|
||||||
|
return new HistoryItem[0];
|
||||||
|
}
|
||||||
|
|
||||||
public virtual bool IsInQueue(RemoteEpisode newEpisode)
|
public virtual bool IsInQueue(RemoteEpisode newEpisode)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -38,6 +38,15 @@ public SabnzbdClient(IConfigService configService,
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsConfigured
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !string.IsNullOrWhiteSpace(_configService.SabHost)
|
||||||
|
&& _configService.SabPort != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string DownloadNzb(RemoteEpisode remoteEpisode)
|
public string DownloadNzb(RemoteEpisode remoteEpisode)
|
||||||
{
|
{
|
||||||
var url = remoteEpisode.Release.DownloadUrl;
|
var url = remoteEpisode.Release.DownloadUrl;
|
||||||
@ -56,15 +65,6 @@ public string DownloadNzb(RemoteEpisode remoteEpisode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsConfigured
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !string.IsNullOrWhiteSpace(_configService.SabHost)
|
|
||||||
&& _configService.SabPort != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<QueueItem> GetQueue()
|
public IEnumerable<QueueItem> GetQueue()
|
||||||
{
|
{
|
||||||
return _queueCache.Get("queue", () =>
|
return _queueCache.Get("queue", () =>
|
||||||
@ -104,7 +104,7 @@ public IEnumerable<QueueItem> GetQueue()
|
|||||||
}, TimeSpan.FromSeconds(10));
|
}, TimeSpan.FromSeconds(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual List<SabHistoryItem> GetHistory(int start = 0, int limit = 0)
|
public IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0)
|
||||||
{
|
{
|
||||||
string action = String.Format("mode=history&output=json&start={0}&limit={1}", start, limit);
|
string action = String.Format("mode=history&output=json&start={0}&limit={1}", start, limit);
|
||||||
string request = GetSabRequest(action);
|
string request = GetSabRequest(action);
|
||||||
@ -113,7 +113,23 @@ public virtual List<SabHistoryItem> GetHistory(int start = 0, int limit = 0)
|
|||||||
CheckForError(response);
|
CheckForError(response);
|
||||||
|
|
||||||
var items = Json.Deserialize<SabHistory>(JObject.Parse(response).SelectToken("history").ToString()).Items;
|
var items = Json.Deserialize<SabHistory>(JObject.Parse(response).SelectToken("history").ToString()).Items;
|
||||||
return items ?? new List<SabHistoryItem>();
|
var historyItems = new List<HistoryItem>();
|
||||||
|
|
||||||
|
foreach (var sabHistoryItem in items)
|
||||||
|
{
|
||||||
|
var historyItem = new HistoryItem();
|
||||||
|
historyItem.Id = sabHistoryItem.Id;
|
||||||
|
historyItem.Title = sabHistoryItem.Title;
|
||||||
|
historyItem.Size = sabHistoryItem.Size;
|
||||||
|
historyItem.DownloadTime = sabHistoryItem.DownloadTime;
|
||||||
|
historyItem.Storage = sabHistoryItem.Storage;
|
||||||
|
historyItem.Category = sabHistoryItem.Category;
|
||||||
|
historyItem.Status = sabHistoryItem.Status == "Failed" ? HistoryStatus.Failed : HistoryStatus.Completed;
|
||||||
|
|
||||||
|
historyItems.Add(historyItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return historyItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual SabCategoryModel GetCategories(string host = null, int port = 0, string apiKey = null, string username = null, string password = null)
|
public virtual SabCategoryModel GetCategories(string host = null, int port = 0, string apiKey = null, string username = null, string password = null)
|
||||||
|
16
src/NzbDrone.Core/Download/DownloadFailedEvent.cs
Normal file
16
src/NzbDrone.Core/Download/DownloadFailedEvent.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download
|
||||||
|
{
|
||||||
|
public class DownloadFailedEvent : IEvent
|
||||||
|
{
|
||||||
|
public Series Series { get; set; }
|
||||||
|
public Episode Episode { get; set; }
|
||||||
|
public QualityModel Quality { get; set; }
|
||||||
|
public String SourceTitle { get; set; }
|
||||||
|
public String DownloadClient { get; set; }
|
||||||
|
public String DownloadClientId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
9
src/NzbDrone.Core/Download/FailedDownloadCommand.cs
Normal file
9
src/NzbDrone.Core/Download/FailedDownloadCommand.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download
|
||||||
|
{
|
||||||
|
public class FailedDownloadCommand : Command
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
87
src/NzbDrone.Core/Download/FailedDownloadService.cs
Normal file
87
src/NzbDrone.Core/Download/FailedDownloadService.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.History;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download
|
||||||
|
{
|
||||||
|
public class FailedDownloadService : IExecute<FailedDownloadCommand>
|
||||||
|
{
|
||||||
|
private readonly IProvideDownloadClient _downloadClientProvider;
|
||||||
|
private readonly IHistoryService _historyService;
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
private static string DOWNLOAD_CLIENT = "downloadClient";
|
||||||
|
private static string DOWNLOAD_CLIENT_ID = "downloadClientId";
|
||||||
|
|
||||||
|
public FailedDownloadService(IProvideDownloadClient downloadClientProvider,
|
||||||
|
IHistoryService historyService,
|
||||||
|
IEventAggregator eventAggregator,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_downloadClientProvider = downloadClientProvider;
|
||||||
|
_historyService = historyService;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckForFailedDownloads()
|
||||||
|
{
|
||||||
|
var downloadClient = _downloadClientProvider.GetDownloadClient();
|
||||||
|
var downloadClientHistory = downloadClient.GetHistory(0, 20).ToList();
|
||||||
|
|
||||||
|
var failedItems = downloadClientHistory.Where(h => h.Status == HistoryStatus.Failed).ToList();
|
||||||
|
|
||||||
|
if (!failedItems.Any())
|
||||||
|
{
|
||||||
|
_logger.Trace("Yay! No failed downloads");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var recentHistory = _historyService.BetweenDates(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, HistoryEventType.Grabbed);
|
||||||
|
var failedHistory = _historyService.Failed();
|
||||||
|
|
||||||
|
foreach (var failedItem in failedItems)
|
||||||
|
{
|
||||||
|
var failedLocal = failedItem;
|
||||||
|
var historyItems = recentHistory.Where(h => h.Data.ContainsKey(DOWNLOAD_CLIENT) &&
|
||||||
|
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (!historyItems.Any())
|
||||||
|
{
|
||||||
|
_logger.Trace("Unable to find matching history item");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failedHistory.Any(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) &&
|
||||||
|
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id)))
|
||||||
|
{
|
||||||
|
_logger.Trace("Already added to history as failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var historyItem in historyItems)
|
||||||
|
{
|
||||||
|
_eventAggregator.PublishEvent(new DownloadFailedEvent
|
||||||
|
{
|
||||||
|
Series = historyItem.Series,
|
||||||
|
Episode = historyItem.Episode,
|
||||||
|
Quality = historyItem.Quality,
|
||||||
|
SourceTitle = historyItem.SourceTitle,
|
||||||
|
DownloadClient = historyItem.Data[DOWNLOAD_CLIENT],
|
||||||
|
DownloadClientId = historyItem.Data[DOWNLOAD_CLIENT_ID]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(FailedDownloadCommand message)
|
||||||
|
{
|
||||||
|
CheckForFailedDownloads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
src/NzbDrone.Core/Download/HistoryItem.cs
Normal file
22
src/NzbDrone.Core/Download/HistoryItem.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download
|
||||||
|
{
|
||||||
|
public class HistoryItem
|
||||||
|
{
|
||||||
|
public String Id { get; set; }
|
||||||
|
public String Title { get; set; }
|
||||||
|
public String Size { get; set; }
|
||||||
|
public String Category { get; set; }
|
||||||
|
public Int32 DownloadTime { get; set; }
|
||||||
|
public String Storage { get; set; }
|
||||||
|
public HistoryStatus Status { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HistoryStatus
|
||||||
|
{
|
||||||
|
Completed = 0,
|
||||||
|
Failed = 1
|
||||||
|
}
|
||||||
|
}
|
@ -8,5 +8,6 @@ public interface IDownloadClient
|
|||||||
string DownloadNzb(RemoteEpisode remoteEpisode);
|
string DownloadNzb(RemoteEpisode remoteEpisode);
|
||||||
bool IsConfigured { get; }
|
bool IsConfigured { get; }
|
||||||
IEnumerable<QueueItem> GetQueue();
|
IEnumerable<QueueItem> GetQueue();
|
||||||
|
IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,9 @@ public History()
|
|||||||
public string SourceTitle { get; set; }
|
public string SourceTitle { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
|
|
||||||
public Episode Episode { get; set; }
|
public Episode Episode { get; set; }
|
||||||
public Series Series { get; set; }
|
public Series Series { get; set; }
|
||||||
|
|
||||||
public HistoryEventType EventType { get; set; }
|
public HistoryEventType EventType { get; set; }
|
||||||
|
|
||||||
public Dictionary<string, string> Data { get; set; }
|
public Dictionary<string, string> Data { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +29,8 @@ public enum HistoryEventType
|
|||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Grabbed = 1,
|
Grabbed = 1,
|
||||||
SeriesFolderImported = 2,
|
SeriesFolderImported = 2,
|
||||||
DownloadFolderImported = 3
|
DownloadFolderImported = 3,
|
||||||
|
DownloadFailed = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -13,6 +13,8 @@ public interface IHistoryRepository : IBasicRepository<History>
|
|||||||
{
|
{
|
||||||
void Trim();
|
void Trim();
|
||||||
List<QualityModel> GetBestQualityInHistory(int episodeId);
|
List<QualityModel> GetBestQualityInHistory(int episodeId);
|
||||||
|
List<History> BetweenDates(DateTime startDate, DateTime endDate, HistoryEventType eventType);
|
||||||
|
List<History> Failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
|
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
|
||||||
@ -38,6 +40,20 @@ public List<QualityModel> GetBestQualityInHistory(int episodeId)
|
|||||||
return history.Select(h => h.Quality).ToList();
|
return history.Select(h => h.Quality).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<History> BetweenDates(DateTime startDate, DateTime endDate, HistoryEventType eventType)
|
||||||
|
{
|
||||||
|
return Query.Join<History, Series>(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id)
|
||||||
|
.Join<History, Episode>(JoinType.Inner, h => h.Episode, (h, e) => h.EpisodeId == e.Id)
|
||||||
|
.Where(h => h.Date >= startDate)
|
||||||
|
.AndWhere(h => h.Date <= endDate)
|
||||||
|
.AndWhere(h => h.EventType == eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<History> Failed()
|
||||||
|
{
|
||||||
|
return Query.Where(h => h.EventType == HistoryEventType.DownloadFailed);
|
||||||
|
}
|
||||||
|
|
||||||
public override PagingSpec<History> GetPaged(PagingSpec<History> pagingSpec)
|
public override PagingSpec<History> GetPaged(PagingSpec<History> pagingSpec)
|
||||||
{
|
{
|
||||||
pagingSpec.Records = GetPagedQuery(pagingSpec).ToList();
|
pagingSpec.Records = GetPagedQuery(pagingSpec).ToList();
|
||||||
|
@ -18,9 +18,11 @@ public interface IHistoryService
|
|||||||
void Trim();
|
void Trim();
|
||||||
QualityModel GetBestQualityInHistory(int episodeId);
|
QualityModel GetBestQualityInHistory(int episodeId);
|
||||||
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
|
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
|
||||||
|
List<History> BetweenDates(DateTime startDate, DateTime endDate, HistoryEventType eventType);
|
||||||
|
List<History> Failed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HistoryService : IHistoryService, IHandle<EpisodeGrabbedEvent>, IHandle<EpisodeImportedEvent>
|
public class HistoryService : IHistoryService, IHandle<EpisodeGrabbedEvent>, IHandle<EpisodeImportedEvent>, IHandle<DownloadFailedEvent>
|
||||||
{
|
{
|
||||||
private readonly IHistoryRepository _historyRepository;
|
private readonly IHistoryRepository _historyRepository;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
@ -41,6 +43,16 @@ public PagingSpec<History> Paged(PagingSpec<History> pagingSpec)
|
|||||||
return _historyRepository.GetPaged(pagingSpec);
|
return _historyRepository.GetPaged(pagingSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<History> BetweenDates(DateTime startDate, DateTime endDate, HistoryEventType eventType)
|
||||||
|
{
|
||||||
|
return _historyRepository.BetweenDates(startDate, endDate, eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<History> Failed()
|
||||||
|
{
|
||||||
|
return _historyRepository.Failed();
|
||||||
|
}
|
||||||
|
|
||||||
public void Purge()
|
public void Purge()
|
||||||
{
|
{
|
||||||
_historyRepository.Purge();
|
_historyRepository.Purge();
|
||||||
@ -51,7 +63,7 @@ public virtual void Trim()
|
|||||||
_historyRepository.Trim();
|
_historyRepository.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual QualityModel GetBestQualityInHistory(int episodeId)
|
public QualityModel GetBestQualityInHistory(int episodeId)
|
||||||
{
|
{
|
||||||
return _historyRepository.GetBestQualityInHistory(episodeId).OrderByDescending(q => q).FirstOrDefault();
|
return _historyRepository.GetBestQualityInHistory(episodeId).OrderByDescending(q => q).FirstOrDefault();
|
||||||
}
|
}
|
||||||
@ -107,5 +119,23 @@ public void Handle(EpisodeImportedEvent message)
|
|||||||
_historyRepository.Insert(history);
|
_historyRepository.Insert(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Handle(DownloadFailedEvent message)
|
||||||
|
{
|
||||||
|
var history = new History
|
||||||
|
{
|
||||||
|
EventType = HistoryEventType.DownloadFailed,
|
||||||
|
Date = DateTime.UtcNow,
|
||||||
|
Quality = message.Quality,
|
||||||
|
SourceTitle = message.SourceTitle,
|
||||||
|
SeriesId = message.Series.Id,
|
||||||
|
EpisodeId = message.Episode.Id,
|
||||||
|
};
|
||||||
|
|
||||||
|
history.Data.Add("DownloadClient", message.DownloadClient);
|
||||||
|
history.Data.Add("DownloadClientId", message.DownloadClientId);
|
||||||
|
|
||||||
|
_historyRepository.Insert(history);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,6 +7,7 @@
|
|||||||
using NzbDrone.Core.DataAugmentation;
|
using NzbDrone.Core.DataAugmentation;
|
||||||
using NzbDrone.Core.DataAugmentation.Scene;
|
using NzbDrone.Core.DataAugmentation.Scene;
|
||||||
using NzbDrone.Core.DataAugmentation.Xem;
|
using NzbDrone.Core.DataAugmentation.Xem;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Housekeeping;
|
using NzbDrone.Core.Housekeeping;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Instrumentation.Commands;
|
using NzbDrone.Core.Instrumentation.Commands;
|
||||||
@ -54,7 +55,8 @@ public void Handle(ApplicationStartedEvent message)
|
|||||||
new ScheduledTask{ Interval = 1*60, TypeName = typeof(TrimLogCommand).FullName},
|
new ScheduledTask{ Interval = 1*60, TypeName = typeof(TrimLogCommand).FullName},
|
||||||
new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
||||||
new ScheduledTask{ Interval = 1, TypeName = typeof(TrackedCommandCleanupCommand).FullName},
|
new ScheduledTask{ Interval = 1, TypeName = typeof(TrackedCommandCleanupCommand).FullName},
|
||||||
new ScheduledTask{ Interval = 24*60, TypeName = typeof(HousekeepingCommand).FullName}
|
new ScheduledTask{ Interval = 24*60, TypeName = typeof(HousekeepingCommand).FullName},
|
||||||
|
new ScheduledTask{ Interval = 1, TypeName = typeof(FailedDownloadCommand).FullName}
|
||||||
};
|
};
|
||||||
|
|
||||||
var currentTasks = _scheduledTaskRepository.All();
|
var currentTasks = _scheduledTaskRepository.All();
|
||||||
|
@ -226,9 +226,13 @@
|
|||||||
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdQueueTimeConverter.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\JsonConverters\SabnzbdQueueTimeConverter.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabAutoConfigureService.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabAutoConfigureService.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabCommunicationProxy.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabCommunicationProxy.cs" />
|
||||||
|
<Compile Include="Download\FailedDownloadCommand.cs" />
|
||||||
|
<Compile Include="Download\HistoryItem.cs" />
|
||||||
|
<Compile Include="Download\DownloadFailedEvent.cs" />
|
||||||
<Compile Include="Download\DownloadApprovedReports.cs" />
|
<Compile Include="Download\DownloadApprovedReports.cs" />
|
||||||
<Compile Include="Download\DownloadClientProvider.cs" />
|
<Compile Include="Download\DownloadClientProvider.cs" />
|
||||||
<Compile Include="Download\DownloadClientType.cs" />
|
<Compile Include="Download\DownloadClientType.cs" />
|
||||||
|
<Compile Include="Download\FailedDownloadService.cs" />
|
||||||
<Compile Include="Download\QueueItem.cs" />
|
<Compile Include="Download\QueueItem.cs" />
|
||||||
<Compile Include="Exceptions\BadRequestException.cs" />
|
<Compile Include="Exceptions\BadRequestException.cs" />
|
||||||
<Compile Include="Exceptions\DownstreamException.cs" />
|
<Compile Include="Exceptions\DownstreamException.cs" />
|
||||||
|
@ -29,6 +29,10 @@ define(
|
|||||||
icon = 'icon-nd-imported';
|
icon = 'icon-nd-imported';
|
||||||
toolTip = 'Episode downloaded successfully and picked up from download client';
|
toolTip = 'Episode downloaded successfully and picked up from download client';
|
||||||
break;
|
break;
|
||||||
|
case 'downloadFailed':
|
||||||
|
icon = 'icon-nd-download-failed';
|
||||||
|
toolTip = 'Episode download failed';
|
||||||
|
break;
|
||||||
default :
|
default :
|
||||||
icon = 'icon-question';
|
icon = 'icon-question';
|
||||||
toolTip = 'unknown event';
|
toolTip = 'unknown event';
|
||||||
|
@ -157,3 +157,8 @@
|
|||||||
.icon(@remove-sign);
|
.icon(@remove-sign);
|
||||||
color : purple;
|
color : purple;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-nd-download-failed:before {
|
||||||
|
.icon(@cloud-download);
|
||||||
|
color: @errorText;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user