Blacklisting will trigger episode search

This commit is contained in:
Mark McDowall 2013-10-23 22:13:04 -07:00
parent 68e40bca29
commit 8520fe3e0c
12 changed files with 197 additions and 48 deletions

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
using NzbDrone.Core.Download;
@ -17,9 +18,9 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
[TestFixture]
public class UpgradeHistorySpecificationFixture : CoreTest<UpgradeHistorySpecification>
public class HistorySpecificationFixture : CoreTest<HistorySpecification>
{
private UpgradeHistorySpecification _upgradeHistory;
private HistorySpecification _upgradeHistory;
private RemoteEpisode _parseResultMulti;
private RemoteEpisode _parseResultSingle;
@ -31,7 +32,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void Setup()
{
Mocker.Resolve<QualityUpgradableSpecification>();
_upgradeHistory = Mocker.Resolve<UpgradeHistorySpecification>();
_upgradeHistory = Mocker.Resolve<HistorySpecification>();
var singleEpisodeList = new List<Episode> { new Episode { Id = 1, SeasonNumber = 12, EpisodeNumber = 3 } };
var doubleEpisodeList = new List<Episode> {
@ -81,6 +82,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(2)).Returns(_upgradableQuality);
}
private void GivenSabnzbdDownloadClient()
{
Mocker.GetMock<IProvideDownloadClient>()
.Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<SabnzbdClient>());
}
private void GivenMostRecentForEpisode(HistoryEventType eventType)
{
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForEpisode(It.IsAny<int>()))
.Returns(new History.History { EventType = eventType });
}
[Test]
public void should_be_upgradable_if_only_episode_is_upgradable()
{
@ -135,12 +148,38 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
}
[Test]
public void should_return_true_if_using_sabnzbd()
public void should_return_true_if_using_sabnzbd_and_nothing_in_history()
{
Mocker.GetMock<IProvideDownloadClient>()
.Setup(c => c.GetDownloadClient()).Returns(Mocker.Resolve<SabnzbdClient>());
GivenSabnzbdDownloadClient();
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, new SeasonSearchCriteria()).Should().BeTrue();
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Should().BeTrue();
}
[Test]
public void should_return_false_if_most_recent_in_history_is_grabbed()
{
GivenSabnzbdDownloadClient();
GivenMostRecentForEpisode(HistoryEventType.Grabbed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Should().BeFalse();
}
[Test]
public void should_return_true_if_most_recent_in_history_is_failed()
{
GivenSabnzbdDownloadClient();
GivenMostRecentForEpisode(HistoryEventType.DownloadFailed);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Should().BeTrue();
}
[Test]
public void should_return_true_if_most_recent_in_history_is_imported()
{
GivenSabnzbdDownloadClient();
GivenMostRecentForEpisode(HistoryEventType.DownloadFolderImported);
_upgradeHistory.IsSatisfiedBy(_parseResultMulti, null).Should().BeTrue();
}
}
}

View File

@ -121,7 +121,6 @@
<Compile Include="Download\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" />
<Compile Include="Download\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" />
<Compile Include="Download\DownloadClientTests\PneumaticProviderFixture.cs" />
<Compile Include="Download\DownloadClientTests\SabProviderTests\QueueFixture.cs" />
<Compile Include="Download\DownloadClientTests\SabProviderTests\SabProviderFixture.cs" />
<Compile Include="Download\DownloadServiceFixture.cs" />
<Compile Include="Download\FailedDownloadServiceFixture.cs" />
@ -194,7 +193,7 @@
<Compile Include="TvTests\EpisodeRepositoryTests\EpisodesBetweenDatesFixture.cs" />
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\QualityAllowedByProfileSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\UpgradeHistorySpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\HistorySpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\UpgradeDiskSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\QualityUpgradeSpecificationFixture.cs" />
<Compile Include="ProviderTests\DiskProviderTests\FreeDiskSpaceFixture.cs" />

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv;
@ -6,8 +7,8 @@ namespace NzbDrone.Core.Blacklisting
{
public class Blacklist : ModelBase
{
public int EpisodeId { get; set; }
public int SeriesId { get; set; }
public List<int> EpisodeIds { get; set; }
public string SourceTitle { get; set; }
public QualityModel Quality { get; set; }
public DateTime Date { get; set; }

View File

@ -15,10 +15,12 @@ namespace NzbDrone.Core.Blacklisting
public class BlacklistService : IBlacklistService, IHandle<DownloadFailedEvent>
{
private readonly IBlacklistRepository _blacklistRepository;
private readonly IRedownloadFailedDownloads _redownloadFailedDownloadService;
public BlacklistService(IBlacklistRepository blacklistRepository)
public BlacklistService(IBlacklistRepository blacklistRepository, IRedownloadFailedDownloads redownloadFailedDownloadService)
{
_blacklistRepository = blacklistRepository;
_redownloadFailedDownloadService = redownloadFailedDownloadService;
}
public bool Blacklisted(string sourceTitle)
@ -30,14 +32,16 @@ namespace NzbDrone.Core.Blacklisting
{
var blacklist = new Blacklist
{
SeriesId = message.Series.Id,
EpisodeId = message.Episode.Id,
SeriesId = message.SeriesId,
EpisodeIds = message.EpisodeIds,
SourceTitle = message.SourceTitle,
Quality = message.Quality,
Date = DateTime.UtcNow
};
_blacklistRepository.Insert(blacklist);
_redownloadFailedDownloadService.Redownload(message.SeriesId, message.EpisodeIds);
}
}
}

View File

@ -10,7 +10,7 @@ namespace NzbDrone.Core.Datastore.Migration
{
Create.TableForModel("Blacklist")
.WithColumn("SeriesId").AsInt32()
.WithColumn("EpisodeId").AsInt32()
.WithColumn("EpisodeIds").AsString()
.WithColumn("SourceTitle").AsString()
.WithColumn("Quality").AsString()
.WithColumn("Date").AsDateTime();

View File

@ -3,18 +3,19 @@ using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.History;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.MetadataSource.Trakt;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
{
public class UpgradeHistorySpecification : IDecisionEngineSpecification
public class HistorySpecification : IDecisionEngineSpecification
{
private readonly IHistoryService _historyService;
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly IProvideDownloadClient _downloadClientProvider;
private readonly Logger _logger;
public UpgradeHistorySpecification(IHistoryService historyService,
public HistorySpecification(IHistoryService historyService,
QualityUpgradableSpecification qualityUpgradableSpecification,
IProvideDownloadClient downloadClientProvider,
Logger logger)
@ -43,7 +44,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
if (_downloadClientProvider.GetDownloadClient().GetType() == typeof (SabnzbdClient))
{
_logger.Trace("Skipping history check in favour of blacklist");
_logger.Trace("Performing history status check on report");
foreach (var episode in subject.Episodes)
{
_logger.Trace("Checking current status of episode [{0}] in history", episode.Id);
var mostRecent = _historyService.MostRecentForEpisode(episode.Id);
if (mostRecent != null && mostRecent.EventType == HistoryEventType.Grabbed)
{
return false;
}
}
return true;
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Tv;
@ -6,8 +7,8 @@ namespace NzbDrone.Core.Download
{
public class DownloadFailedEvent : IEvent
{
public Series Series { get; set; }
public Episode Episode { get; set; }
public Int32 SeriesId { get; set; }
public List<Int32> EpisodeIds { get; set; }
public QualityModel Quality { get; set; }
public String SourceTitle { get; set; }
public String DownloadClient { get; set; }

View File

@ -41,15 +41,15 @@ namespace NzbDrone.Core.Download
return;
}
var recentHistory = _historyService.BetweenDates(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, HistoryEventType.Grabbed);
var grabbedHistory = _historyService.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();
var historyItems = grabbedHistory.Where(h => h.Data.ContainsKey(DOWNLOAD_CLIENT) &&
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id))
.ToList();
if (!historyItems.Any())
{
@ -64,18 +64,17 @@ namespace NzbDrone.Core.Download
continue;
}
foreach (var historyItem in historyItems)
var historyItem = historyItems.First();
_eventAggregator.PublishEvent(new DownloadFailedEvent
{
_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]
});
}
SeriesId = historyItem.SeriesId,
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(),
Quality = historyItem.Quality,
SourceTitle = historyItem.SourceTitle,
DownloadClient = historyItem.Data[DOWNLOAD_CLIENT],
DownloadClientId = historyItem.Data[DOWNLOAD_CLIENT_ID]
});
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.IndexerSearch;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Download
{
public interface IRedownloadFailedDownloads
{
void Redownload(int seriesId, List<int> episodeIds);
}
public class RedownloadFailedDownloadService : IRedownloadFailedDownloads
{
private readonly IEpisodeService _episodeService;
private readonly ICommandExecutor _commandExecutor;
private readonly Logger _logger;
public RedownloadFailedDownloadService(IEpisodeService episodeService, ICommandExecutor commandExecutor, Logger logger)
{
_episodeService = episodeService;
_commandExecutor = commandExecutor;
_logger = logger;
}
public void Redownload(int seriesId, List<int> episodeIds)
{
if (episodeIds.Count == 1)
{
_logger.Trace("Failed download only contains one episode, searching again");
_commandExecutor.PublishCommandAsync(new EpisodeSearchCommand
{
EpisodeIds = episodeIds.ToList()
});
return;
}
var seasonNumber = _episodeService.GetEpisode(episodeIds.First()).SeasonNumber;
var episodesInSeason = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber);
if (episodeIds.Count == episodesInSeason.Count)
{
_logger.Trace("Failed download was entire season, searching again");
_commandExecutor.PublishCommandAsync(new SeasonSearchCommand
{
SeriesId = seriesId,
SeasonNumber = seasonNumber
});
return;
}
_logger.Trace("Failed download contains multiple episodes, probably a double episode, searching again");
_commandExecutor.PublishCommandAsync(new EpisodeSearchCommand
{
EpisodeIds = episodeIds.ToList()
});
}
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Marr.Data.QGen;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
@ -15,6 +14,8 @@ namespace NzbDrone.Core.History
List<QualityModel> GetBestQualityInHistory(int episodeId);
List<History> BetweenDates(DateTime startDate, DateTime endDate, HistoryEventType eventType);
List<History> Failed();
List<History> Grabbed();
History MostRecentForEpisode(int episodeId);
}
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
@ -54,6 +55,18 @@ namespace NzbDrone.Core.History
return Query.Where(h => h.EventType == HistoryEventType.DownloadFailed);
}
public List<History> Grabbed()
{
return Query.Where(h => h.EventType == HistoryEventType.Grabbed);
}
public History MostRecentForEpisode(int episodeId)
{
return Query.Where(h => h.EpisodeId == episodeId)
.OrderByDescending(h => h.Date)
.FirstOrDefault();
}
public override PagingSpec<History> GetPaged(PagingSpec<History> pagingSpec)
{
pagingSpec.Records = GetPagedQuery(pagingSpec).ToList();

View File

@ -20,6 +20,8 @@ namespace NzbDrone.Core.History
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
List<History> BetweenDates(DateTime startDate, DateTime endDate, HistoryEventType eventType);
List<History> Failed();
List<History> Grabbed();
History MostRecentForEpisode(int episodeId);
}
public class HistoryService : IHistoryService, IHandle<EpisodeGrabbedEvent>, IHandle<EpisodeImportedEvent>, IHandle<DownloadFailedEvent>
@ -53,6 +55,16 @@ namespace NzbDrone.Core.History
return _historyRepository.Failed();
}
public List<History> Grabbed()
{
return _historyRepository.Grabbed();
}
public History MostRecentForEpisode(int episodeId)
{
return _historyRepository.MostRecentForEpisode(episodeId);
}
public void Purge()
{
_historyRepository.Purge();
@ -122,20 +134,23 @@ namespace NzbDrone.Core.History
public void Handle(DownloadFailedEvent message)
{
var history = new History
foreach (var episodeId in message.EpisodeIds)
{
EventType = HistoryEventType.DownloadFailed,
Date = DateTime.UtcNow,
Quality = message.Quality,
SourceTitle = message.SourceTitle,
SeriesId = message.Series.Id,
EpisodeId = message.Episode.Id,
};
var history = new History
{
EventType = HistoryEventType.DownloadFailed,
Date = DateTime.UtcNow,
Quality = message.Quality,
SourceTitle = message.SourceTitle,
SeriesId = message.SeriesId,
EpisodeId = episodeId,
};
history.Data.Add("DownloadClient", message.DownloadClient);
history.Data.Add("DownloadClientId", message.DownloadClientId);
history.Data.Add("DownloadClient", message.DownloadClient);
history.Data.Add("DownloadClientId", message.DownloadClientId);
_historyRepository.Insert(history);
_historyRepository.Insert(history);
}
}
}
}

View File

@ -223,7 +223,7 @@
<Compile Include="DecisionEngine\QualityUpgradableSpecification.cs" />
<Compile Include="DecisionEngine\Specifications\Search\SingleEpisodeSearchMatchSpecification.cs" />
<Compile Include="DecisionEngine\Specifications\UpgradeDiskSpecification.cs" />
<Compile Include="DecisionEngine\Specifications\RssSync\UpgradeHistorySpecification.cs" />
<Compile Include="DecisionEngine\Specifications\RssSync\HistorySpecification.cs" />
<Compile Include="DiskSpace\DiskSpace.cs" />
<Compile Include="DiskSpace\DiskSpaceService.cs" />
<Compile Include="Download\Clients\Sabnzbd\ConnectionInfoModel.cs" />
@ -239,6 +239,7 @@
<Compile Include="Download\DownloadClientType.cs" />
<Compile Include="Download\FailedDownloadService.cs" />
<Compile Include="Download\QueueItem.cs" />
<Compile Include="Download\RedownloadFailedDownloadService.cs" />
<Compile Include="Exceptions\BadRequestException.cs" />
<Compile Include="Exceptions\DownstreamException.cs" />
<Compile Include="Exceptions\NzbDroneClientException.cs" />
@ -358,7 +359,6 @@
<Compile Include="IndexerSearch\Definitions\SeasonSearchCriteria.cs" />
<Compile Include="IndexerSearch\Definitions\SingleEpisodeSearchCriteria.cs" />
<Compile Include="IndexerSearch\NzbSearchService.cs" />
<Compile Include="IndexerSearch\SearchAndDownloadService.cs" />
<Compile Include="Indexers\RssParserBase.cs" />
<Compile Include="Indexers\RssSyncService.cs" />
<Compile Include="Indexers\IndexerBase.cs" />