Added two new Episode Statuses - Unpacking and Failed.

Tests added to support new Statuses.
PostDownloadScanJob will update PostDownloadStatus for failed or unpacking.
ImportFile will set the PostDownloadStatus to Processed when added to the database.
pull/6/head
Mark McDowall 13 years ago
parent c534d47b0a
commit 5098ea3249

@ -7,6 +7,7 @@ using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
@ -1464,5 +1465,42 @@ namespace NzbDrone.Core.Test
//Assert
result.Should().BeFalse();
}
[TestCase("The Office (US) - S01E05 - Episode Title", PostDownloadStatusType.Unpacking, 1)]
[TestCase("The Office (US) - S01E05 - Episode Title", PostDownloadStatusType.Failed, 1)]
[TestCase("The Office (US) - S01E05E06 - Episode Title", PostDownloadStatusType.Unpacking, 2)]
[TestCase("The Office (US) - S01E05E06 - Episode Title", PostDownloadStatusType.Failed, 2)]
[TestCase("The Office (US) - Season 01 - Episode Title", PostDownloadStatusType.Unpacking, 10)]
[TestCase("The Office (US) - Season 01 - Episode Title", PostDownloadStatusType.Failed, 10)]
public void SetPostDownloadStatus(string folderName, PostDownloadStatusType postDownloadStatus, int episodeCount)
{
var db = MockLib.GetEmptyDatabase();
var mocker = new AutoMoqer();
mocker.SetConstant(db);
var fakeSeries = Builder<Series>.CreateNew()
.With(s => s.SeriesId = 12345)
.With(s => s.CleanTitle = "officeus")
.Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll()
.Have(c => c.SeriesId = 12345)
.Have(c => c.SeasonNumber = 1)
.Have(c => c.PostDownloadStatus = PostDownloadStatusType.Unknown)
.Build();
db.Insert(fakeSeries);
db.InsertMany(fakeEpisodes);
mocker.GetMock<SeriesProvider>().Setup(s => s.FindSeries("officeus")).Returns(fakeSeries);
//Act
mocker.Resolve<EpisodeProvider>().SetPostDownloadStatus(folderName, postDownloadStatus);
//Assert
var result = db.Fetch<Episode>();
result.Where(e => e.PostDownloadStatus == postDownloadStatus).Count().Should().Be(episodeCount);
}
}
}

@ -101,7 +101,6 @@ namespace NzbDrone.Core.Test
db.Fetch<Episode>().Should().HaveCount(1);
}
[Test]
public void Multi_GetSeason_Episode_Exists()
{
@ -235,5 +234,69 @@ namespace NzbDrone.Core.Test
db.Fetch<Episode>().Should().HaveCount(2);
ep.First().Ignored.Should().BeFalse();
}
[Test]
public void Full_Season_return_all_episodes_for_season()
{
var mocker = new AutoMoqer();
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll()
.Have(e => e.SeriesId = fakeSeries.SeriesId)
.Have(e => e.SeasonNumber = 2)
.Build();
db.Insert(fakeSeries);
db.InsertMany(fakeEpisodes);
var parseResult = new EpisodeParseResult
{
Series = fakeSeries,
SeasonNumber = 2,
EpisodeNumbers = new List<int>(),
FullSeason = true
};
var ep = mocker.Resolve<EpisodeProvider>().GetEpisodesByParseResult(parseResult);
ep.Should().HaveCount(10);
db.Fetch<Episode>().Should().HaveCount(10);
}
[Test]
public void No_Episodes_Not_a_proper_full_season_release()
{
var mocker = new AutoMoqer();
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll()
.Have(e => e.SeriesId = fakeSeries.SeriesId)
.Have(e => e.SeasonNumber = 2)
.Build();
db.Insert(fakeSeries);
db.InsertMany(fakeEpisodes);
var parseResult = new EpisodeParseResult
{
Series = fakeSeries,
SeasonNumber = 2,
EpisodeNumbers = new List<int>(),
FullSeason = false
};
var ep = mocker.Resolve<EpisodeProvider>().GetEpisodesByParseResult(parseResult);
ep.Should().HaveCount(0);
db.Fetch<Episode>().Should().HaveCount(10);
}
}
}

@ -108,5 +108,27 @@ namespace NzbDrone.Core.Test
episode.Status.Should().Be(EpisodeStatusType.NotAired);
}
[TestCase(false, false, EpisodeStatusType.Failed, PostDownloadStatusType.Failed)]
[TestCase(false, false, EpisodeStatusType.Unpacking, PostDownloadStatusType.Unpacking)]
[TestCase(true, false, EpisodeStatusType.Ready, PostDownloadStatusType.Failed)]
[TestCase(true, true, EpisodeStatusType.Ready, PostDownloadStatusType.Unpacking)]
public void episode_downloaded_post_download_status_is_used(bool hasEpisodes, bool ignored,
EpisodeStatusType status, PostDownloadStatusType postDownloadStatus)
{
Episode episode = Builder<Episode>.CreateNew()
.With(e => e.Ignored = ignored)
.With(e => e.EpisodeFileId = 0)
.With(e => e.GrabDate = DateTime.Now.AddHours(22))
.With(e => e.PostDownloadStatus = postDownloadStatus)
.Build();
if (hasEpisodes)
{
episode.EpisodeFileId = 12;
}
Assert.AreEqual(status, episode.Status);
}
}
}

@ -21,7 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

@ -0,0 +1,21 @@
using System;
using System.Data;
using Migrator.Framework;
namespace NzbDrone.Core.Datastore.Migrations
{
[Migration(20111011)]
public class Migration20111011 : Migration
{
public override void Up()
{
Database.AddColumn("Episodes", "PostDownloadStatus", DbType.Int32, ColumnProperty.Null);
}
public override void Down()
{
throw new NotImplementedException();
}
}
}

@ -5,7 +5,7 @@
/// <summary>
/// Episode has not aired yet
/// </summary>
NotAired ,
NotAired,
/// <summary>
/// Episode is ignored
@ -16,12 +16,22 @@
/// Episode has aired but no episode
/// files have avilable
/// </summary>
Missing ,
Missing,
/// <summary>
/// Episode is being downloaded
/// </summary>
Downloading ,
Downloading,
/// <summary>
/// Episode has been downloaded and is unpacking (_UNPACK_)
/// </summary>
Unpacking,
/// <summary>
/// Episode has failed to download properly (_FAILED_)
/// </summary>
Failed,
/// <summary>
/// Episode is present in disk

@ -0,0 +1,25 @@
namespace NzbDrone.Core.Model
{
public enum PostDownloadStatusType
{
/// <summary>
/// Unknown (Default)
/// </summary>
Unknown = 0,
/// <summary>
/// Unpacking
/// </summary>
Unpacking = 1,
/// <summary>
/// Failed
/// </summary>
Failed = 2,
/// <summary>
/// Processed
/// </summary>
Processed = 3
}
}

@ -176,6 +176,7 @@
<Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\MigrationsHelper.cs" />
<Compile Include="Datastore\CustomeMapper.cs" />
<Compile Include="Datastore\Migrations\Migration20111011.cs" />
<Compile Include="Datastore\Migrations\Migration20110909.cs" />
<Compile Include="Datastore\Migrations\Migration20110726.cs" />
<Compile Include="Datastore\Migrations\Migration20110707.cs" />
@ -192,6 +193,7 @@
<Compile Include="Model\AtomicParsleyTitleType.cs" />
<Compile Include="Model\AuthenticationType.cs" />
<Compile Include="Model\ConnectionInfoModel.cs" />
<Compile Include="Model\PostDownloadStatusType.cs" />
<Compile Include="Model\ExternalNotificationType.cs" />
<Compile Include="Model\JobQueueItem.cs" />
<Compile Include="Model\LanguageType.cs" />

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using Ninject;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using PetaPoco;
@ -146,6 +147,7 @@ namespace NzbDrone.Core.Providers
foreach (var ep in episodes)
{
ep.EpisodeFileId = fileId;
ep.PostDownloadStatus = PostDownloadStatusType.Processed;
_episodeProvider.UpdateEpisode(ep);
Logger.Debug("Linking [{0}] > [{1}]", filePath, ep);
}

@ -125,6 +125,14 @@ namespace NzbDrone.Core.Providers
{
var result = new List<Episode>();
if (parseResult.EpisodeNumbers.Count == 0 && parseResult.FullSeason)
{
result.AddRange(GetEpisodesBySeason(parseResult.Series.SeriesId, parseResult.SeasonNumber));
//Return now as no further processing is required
return result;
}
foreach (var episodeNumber in parseResult.EpisodeNumbers)
{
var episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber);
@ -396,5 +404,20 @@ namespace NzbDrone.Core.Providers
Logger.Trace("Finished deleting invalid episodes for {0}", series.SeriesId);
}
public virtual void SetPostDownloadStatus(string folderName, PostDownloadStatusType postDownloadStatus)
{
var parseResult = Parser.ParseTitle(folderName);
parseResult.Series = _seriesProvider.FindSeries(parseResult.CleanTitle);
var episodeIds = GetEpisodesByParseResult(parseResult).Select(e => e.EpisodeId);
var episodeIdString = String.Join(", ", episodeIds);
var episodeIdQuery = String.Format(@"UPDATE Episodes SET PostDownloadStatus = {0}
WHERE EpisodeId IN ({1})", (int)postDownloadStatus, episodeIdString);
Logger.Trace("Updating PostDownloadStatus for all episodeIds in {0}", episodeIdString);
_database.Execute(episodeIdQuery);
}
}
}

@ -2,6 +2,7 @@
using System.IO;
using Ninject;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Core;
@ -13,16 +14,19 @@ namespace NzbDrone.Core.Providers.Jobs
private readonly DiskProvider _diskProvider;
private readonly DiskScanProvider _diskScanProvider;
private readonly SeriesProvider _seriesProvider;
private readonly EpisodeProvider _episodeProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
[Inject]
public PostDownloadScanJob(ConfigProvider configProvider, DiskProvider diskProvider,
DiskScanProvider diskScanProvider, SeriesProvider seriesProvider)
DiskScanProvider diskScanProvider, SeriesProvider seriesProvider,
EpisodeProvider episodeProvider)
{
_configProvider = configProvider;
_diskProvider = diskProvider;
_diskScanProvider = diskScanProvider;
_seriesProvider = seriesProvider;
_episodeProvider = episodeProvider;
}
public PostDownloadScanJob()
@ -63,12 +67,14 @@ namespace NzbDrone.Core.Providers.Jobs
if (subfolderInfo.Name.StartsWith("_UNPACK_", StringComparison.CurrentCultureIgnoreCase))
{
_episodeProvider.SetPostDownloadStatus(subfolderInfo.Name.Substring(8), PostDownloadStatusType.Unpacking);
Logger.Debug("Folder [{0}] is still being unpacked. skipping.", subfolder);
continue;
}
if (subfolderInfo.Name.StartsWith("_FAILED_", StringComparison.CurrentCultureIgnoreCase))
{
_episodeProvider.SetPostDownloadStatus(subfolderInfo.Name.Substring(8), PostDownloadStatusType.Failed);
Logger.Debug("Folder [{0}] is marked as failed. skipping.", subfolder);
continue;
}

@ -23,6 +23,8 @@ namespace NzbDrone.Core.Repository
public Boolean Ignored { get; set; }
public PostDownloadStatusType PostDownloadStatus { get; set; }
/// <summary>
/// Gets or sets the grab date.
/// </summary>
@ -39,15 +41,23 @@ namespace NzbDrone.Core.Repository
{
if (EpisodeFileId != 0) return EpisodeStatusType.Ready;
if (GrabDate != null && GrabDate.Value.AddDays(1) >= DateTime.Now)
if (GrabDate != null)
{
return EpisodeStatusType.Downloading;
if (PostDownloadStatus == PostDownloadStatusType.Unpacking)
return EpisodeStatusType.Unpacking;
if (PostDownloadStatus == PostDownloadStatusType.Failed)
return EpisodeStatusType.Failed;
if (GrabDate.Value.AddDays(1) >= DateTime.Now)
return EpisodeStatusType.Downloading;
}
if (GrabDate != null && GrabDate.Value.AddDays(1) >= DateTime.Now)
return EpisodeStatusType.Downloading;
if (AirDate != null && AirDate.Value.Date < DateTime.Now)
{
return EpisodeStatusType.Missing;
}
return EpisodeStatusType.NotAired;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

@ -333,6 +333,7 @@
<Content Include="Content\Images\close.png" />
<Content Include="Content\Images\Downloading.png" />
<Content Include="Content\Images\error.png" />
<Content Include="Content\Images\Failed.png" />
<Content Include="Content\Images\gritter.png" />
<Content Include="Content\Images\Missing.png" />
<Content Include="Content\Images\NotAired.png" />
@ -340,6 +341,7 @@
<Content Include="Content\Images\Rename.png" />
<Content Include="Content\Images\Search.png" />
<Content Include="Content\Images\success.png" />
<Content Include="Content\Images\Unpacking.png" />
<Content Include="Content\jquery.gritter.css" />
<Content Include="Content\Menu.css" />
<Compile Include="App_GlobalResources\EditorLocalization.bg-BG.designer.cs">

Loading…
Cancel
Save