From 4da2e1cb726ec3470dfb6655e1df87e085825e96 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Mon, 16 Jan 2012 20:05:36 -0800 Subject: [PATCH] Episode auto-ignore is now done in realtime rather than using a job. --- .../JobTests/DiskScanJobTest.cs | 11 -- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 3 +- .../ProviderTests/DiskScanProviderTest.cs | 7 +- .../ProviderTests/EpisodeProviderTest.cs | 34 ----- ...viderTests.cs => MediaFileProviderTest.cs} | 61 ++------ .../CleanUpDatabaseFixture.cs | 134 ++++++++++++++++++ NzbDrone.Core/CentralDispatch.cs | 1 - NzbDrone.Core/Jobs/AutoIgnoreJob.cs | 51 ------- NzbDrone.Core/Jobs/DiskScanJob.cs | 8 +- NzbDrone.Core/NzbDrone.Core.csproj | 1 - NzbDrone.Core/Providers/DiskScanProvider.cs | 8 +- NzbDrone.Core/Providers/EpisodeProvider.cs | 8 -- NzbDrone.Core/Providers/MediaFileProvider.cs | 35 ++--- 13 files changed, 171 insertions(+), 191 deletions(-) rename NzbDrone.Core.Test/ProviderTests/{MediaFileProviderTests.cs => MediaFileProviderTest.cs} (75%) create mode 100644 NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests/CleanUpDatabaseFixture.cs delete mode 100644 NzbDrone.Core/Jobs/AutoIgnoreJob.cs diff --git a/NzbDrone.Core.Test/JobTests/DiskScanJobTest.cs b/NzbDrone.Core.Test/JobTests/DiskScanJobTest.cs index 677bf7c4d..b9500df52 100644 --- a/NzbDrone.Core.Test/JobTests/DiskScanJobTest.cs +++ b/NzbDrone.Core.Test/JobTests/DiskScanJobTest.cs @@ -37,9 +37,6 @@ namespace NzbDrone.Core.Test.JobTests .Setup(p => p.Scan(series)) .Returns(new List()); - Mocker.GetMock() - .Setup(s => s.Start(It.IsAny(), 0, 0)); - //Act Mocker.Resolve().Start(new ProgressNotification("Test"), series.SeriesId, 0); @@ -71,9 +68,6 @@ namespace NzbDrone.Core.Test.JobTests .Setup(s => s.Scan(series[1])) .Returns(new List()); - Mocker.GetMock() - .Setup(s => s.Start(It.IsAny(), 0, 0)); - Mocker.Resolve().Start(new ProgressNotification("Test"), 0, 0); @@ -102,9 +96,6 @@ namespace NzbDrone.Core.Test.JobTests .Setup(s => s.Scan(series[1])) .Throws(new InvalidOperationException("Bad Job")); - Mocker.GetMock() - .Setup(s => s.Start(It.IsAny(), 0, 0)); - Mocker.Resolve().Start(new ProgressNotification("Test"), 0, 0); @@ -134,8 +125,6 @@ namespace NzbDrone.Core.Test.JobTests .Setup(s => s.Scan(series[1])) .Returns(new List()); - Mocker.GetMock() - .Setup(s => s.Start(It.IsAny(), 0, 0)); Mocker.Resolve().Start(new ProgressNotification("Test"), 0, 0); diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 24241cdaf..01deffe50 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -102,6 +102,7 @@ + @@ -151,7 +152,7 @@ - + diff --git a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest.cs index 45eb958d8..d494bffcb 100644 --- a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTest.cs @@ -147,13 +147,10 @@ namespace NzbDrone.Core.Test.ProviderTests .With(s => s.Path = @"C:\Test\TV\SeriesName\") .Build(); - Mocker.GetMock() - .Setup(c => c.DeleteOrphaned()) - .Returns(0); Mocker.GetMock() - .Setup(c => c.RepairLinks()) - .Returns(0); + .Setup(c => c.CleanUpDatabase()); + Mocker.GetMock() .Setup(c => c.FolderExists(series.Path)) diff --git a/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest.cs b/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest.cs index 08d57a801..a476f8bfc 100644 --- a/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest.cs +++ b/NzbDrone.Core.Test/ProviderTests/EpisodeProviderTest.cs @@ -1590,39 +1590,5 @@ namespace NzbDrone.Core.Test.ProviderTests result.Where(e => e.Ignored).Should().HaveCount(episodeCount - 1); result.Single(e => e.SeasonNumber == 1).Ignored.Should().BeFalse(); } - - [Test] - public void SetPreviouslyDownloadedToIgnored_should_set_only_episodes_with_no_episode_file_and_postdownload_status_noError_to_ignored() - { - WithRealDb(); - - var postDownloadStatus = PostDownloadStatusType.NoError; - - var fakeEpisodes = Builder.CreateListOfSize(10) - .All() - .With(c => c.Ignored = false) - .TheFirst(2) - .With(c => c.PostDownloadStatus = PostDownloadStatusType.NoError) - .With(c => c.EpisodeFileId = 0) - .TheNext(3) - .With(c => c.PostDownloadStatus = PostDownloadStatusType.Unknown) - .With(c => c.EpisodeFileId = 0) - .TheNext(4) - .With(c => c.PostDownloadStatus = PostDownloadStatusType.NoError) - .TheNext(1) - .With(c => c.PostDownloadStatus = PostDownloadStatusType.NoError) - .With(c => c.Ignored = true) - .Build(); - - Db.InsertMany(fakeEpisodes); - - //Act - Mocker.Resolve().SetPreviouslyDownloadedToIgnored(); - - //Assert - var result = Db.Fetch(); - result.Should().HaveCount(10); - result.Where(e => e.Ignored).Count().Should().Be(3); - } } } diff --git a/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests.cs b/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTest.cs similarity index 75% rename from NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests.cs rename to NzbDrone.Core.Test/ProviderTests/MediaFileProviderTest.cs index 36b1850f4..5e8b0d052 100644 --- a/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests.cs +++ b/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTest.cs @@ -1,5 +1,6 @@ // ReSharper disable RedundantUsingDirective +using System; using System.Collections.Generic; using FizzWare.NBuilder; @@ -7,6 +8,7 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Common; +using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; @@ -17,7 +19,7 @@ namespace NzbDrone.Core.Test.ProviderTests { [TestFixture] // ReSharper disable InconsistentNaming - public class MediaFileProviderTests : CoreTest + public class MediaFileProviderTest : CoreTest { [Test] public void get_series_files() @@ -28,7 +30,7 @@ namespace NzbDrone.Core.Test.ProviderTests var secondSeriesFiles = Builder.CreateListOfSize(10) .All().With(s => s.SeriesId = 20).Build(); - + var database = TestDbHelper.GetEmptyDatabase(true); @@ -59,7 +61,7 @@ namespace NzbDrone.Core.Test.ProviderTests .With(s => s.SeasonNumber = 2) .Build(); - + var database = TestDbHelper.GetEmptyDatabase(true); @@ -83,15 +85,13 @@ namespace NzbDrone.Core.Test.ProviderTests .Returns(new List()); Mocker.GetMock() - .Setup(e => e.RepairLinks()).Returns(0); + .Setup(e => e.CleanUpDatabase()); - Mocker.GetMock() - .Setup(e => e.DeleteOrphaned()).Returns(0); Mocker.GetMock() .Setup(c => c.FolderExists(It.IsAny())) .Returns(true); - + var series = Builder.CreateNew() .With(s => s.SeriesId = 12).Build(); @@ -114,49 +114,6 @@ namespace NzbDrone.Core.Test.ProviderTests Assert.AreEqual(expectedName, result); } - [Test] - public void CleanEpisodesWithNonExistantFiles() - { - //Setup - var episodes = Builder.CreateListOfSize(10).Build(); - - - var database = TestDbHelper.GetEmptyDatabase(true); - Mocker.SetConstant(database); - database.InsertMany(episodes); - - //Act - var removedLinks = Mocker.Resolve().RepairLinks(); - var result = database.Fetch(); - - //Assert - result.Should().HaveSameCount(episodes); - result.Should().OnlyContain(e => e.EpisodeFileId == 0); - removedLinks.Should().Be(10); - } - - [Test] - public void DeleteOrphanedEpisodeFiles() - { - //Setup - var episodeFiles = Builder.CreateListOfSize(10).Build(); - var episodes = Builder.CreateListOfSize(5).Build(); - - - var database = TestDbHelper.GetEmptyDatabase(true); - Mocker.SetConstant(database); - database.InsertMany(episodes); - database.InsertMany(episodeFiles); - - //Act - Mocker.Resolve().DeleteOrphaned(); - var result = database.Fetch(); - - //Assert - result.Should().HaveCount(5); - result.Should().OnlyContain(e => e.EpisodeFileId > 0); - } - [Test] [TestCase("30 Rock - S01E05 - Episode Title", 1, true, "Season %0s", @"C:\Test\30 Rock\Season 01\30 Rock - S01E05 - Episode Title.mkv")] [TestCase("30 Rock - S01E05 - Episode Title", 1, true, "Season %s", @"C:\Test\30 Rock\Season 1\30 Rock - S01E05 - Episode Title.mkv")] @@ -172,7 +129,7 @@ namespace NzbDrone.Core.Test.ProviderTests .With(s => s.SeasonFolder = useSeasonFolder) .Build(); - + Mocker.GetMock().Setup(e => e.SortingSeasonFolderFormat).Returns(seasonFolderFormat); //Act @@ -188,7 +145,7 @@ namespace NzbDrone.Core.Test.ProviderTests //Setup var episodeFiles = Builder.CreateListOfSize(10).Build(); - + var database = TestDbHelper.GetEmptyDatabase(true); Mocker.SetConstant(database); database.InsertMany(episodeFiles); diff --git a/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests/CleanUpDatabaseFixture.cs b/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests/CleanUpDatabaseFixture.cs new file mode 100644 index 000000000..5ff88752e --- /dev/null +++ b/NzbDrone.Core.Test/ProviderTests/MediaFileProviderTests/CleanUpDatabaseFixture.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Model; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ProviderTests.MediaFileProviderTests +{ + [TestFixture] + public class CleanUpDatabaseFixture : CoreTest + { + + [SetUp] + public void Setup() + { + WithRealDb(); + } + + private void WithAutoIgnore(bool autoIgnore) + { + + Mocker.GetMock() + .SetupGet(c => c.AutoIgnorePreviouslyDownloadedEpisodes).Returns(autoIgnore); + } + + + + [Test] + public void CleanUpDatabse_should_detach_none_existing_file_from_episodes_with_auto_ignore() + { + WithAutoIgnore(true); + + var episodes = Builder.CreateListOfSize(3) + .All().With(c => c.GrabDate = DateTime.Now) + .And(c => c.Ignored = false) + .And(c => c.PostDownloadStatus = PostDownloadStatusType.NoError) + .Build(); + + + Db.InsertMany(episodes); + + //Act + Mocker.Resolve().CleanUpDatabase(); + var result = Db.Fetch(); + + //Assert + result.Should().HaveSameCount(episodes); + result.Should().OnlyContain(e => e.EpisodeFileId == 0); + result.Should().OnlyContain(e => e.PostDownloadStatus == PostDownloadStatusType.Unknown); + result.Should().OnlyContain(e => e.Ignored); + result.Should().OnlyContain(e => e.GrabDate == null); + } + + [Test] + public void CleanUpDatabse_should_detach_none_existing_file_from_episodes_with_no_auto_ignore() + { + WithAutoIgnore(false); + + var episodes = Builder.CreateListOfSize(3) + .All().With(c => c.GrabDate = DateTime.Now) + .And(c => c.PostDownloadStatus = PostDownloadStatusType.NoError) + .TheFirst(2).With(c => c.Ignored = true) + .TheLast(1).With(c => c.Ignored = false) + .Build(); + + + Db.InsertMany(episodes); + + //Act + Mocker.Resolve().CleanUpDatabase(); + var result = Db.Fetch(); + + //Assert + result.Should().HaveSameCount(episodes); + result.Should().OnlyContain(e => e.EpisodeFileId == 0); + result.Should().OnlyContain(e => e.PostDownloadStatus == PostDownloadStatusType.Unknown); + result.Should().OnlyContain(e => e.GrabDate == null); + result.Should().Contain(c => c.Ignored == true); + result.Should().Contain(c => c.Ignored == false); + } + + [Test] + public void CleanUpDatabse_should_not_change_episodes_with_no_file_id() + { + //Setup + var episodes = Builder.CreateListOfSize(3) + .All().With(c => c.GrabDate = DateTime.Now) + .And(c => c.Ignored = false) + .And(c => c.PostDownloadStatus = PostDownloadStatusType.NoError) + .And(c => c.EpisodeFileId = 0) + .Build(); + + Db.InsertMany(episodes); + + //Act + Mocker.Resolve().CleanUpDatabase(); + var result = Db.Fetch(); + + //Assert + result.Should().HaveSameCount(episodes); + result.Should().OnlyContain(e => e.EpisodeFileId == 0); + result.Should().NotContain(e => e.PostDownloadStatus == PostDownloadStatusType.Unknown); + result.Should().NotContain(e => e.Ignored); + result.Should().NotContain(e => e.GrabDate == null); + } + + + [Test] + public void DeleteOrphanedEpisodeFiles() + { + //Setup + var episodeFiles = Builder.CreateListOfSize(10).Build(); + var episodes = Builder.CreateListOfSize(5).Build(); + + Db.InsertMany(episodes); + Db.InsertMany(episodeFiles); + + //Act + Mocker.Resolve().CleanUpDatabase(); + var result = Db.Fetch(); + + //Assert + result.Should().HaveCount(5); + result.Should().OnlyContain(e => e.EpisodeFileId > 0); + } + } +} diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs index b41f4a7e1..ffc289e01 100644 --- a/NzbDrone.Core/CentralDispatch.cs +++ b/NzbDrone.Core/CentralDispatch.cs @@ -96,7 +96,6 @@ namespace NzbDrone.Core Kernel.Bind().To().InSingletonScope(); Kernel.Bind().To().InSingletonScope(); Kernel.Bind().To().InSingletonScope(); - Kernel.Bind().To().InSingletonScope(); Kernel.Get().Initialize(); Kernel.Get().StartTimer(30); diff --git a/NzbDrone.Core/Jobs/AutoIgnoreJob.cs b/NzbDrone.Core/Jobs/AutoIgnoreJob.cs deleted file mode 100644 index 4853b2a84..000000000 --- a/NzbDrone.Core/Jobs/AutoIgnoreJob.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Ninject; -using NLog; -using NzbDrone.Core.Helpers; -using NzbDrone.Core.Model.Notification; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Core; -using NzbDrone.Core.Repository; - -namespace NzbDrone.Core.Jobs -{ - public class AutoIgnoreJob : IJob - { - private readonly ConfigProvider _configProvider; - private readonly EpisodeProvider _episodeProvider; - - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - [Inject] - public AutoIgnoreJob(ConfigProvider configProvider, EpisodeProvider episodeProvider) - { - _configProvider = configProvider; - _episodeProvider = episodeProvider; - } - - public AutoIgnoreJob() - { - } - - public string Name - { - get { return "Auto Ignore Episodes"; } - } - - public TimeSpan DefaultInterval - { - get { return TimeSpan.FromTicks(0); } - } - - public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId) - { - if (_configProvider.AutoIgnorePreviouslyDownloadedEpisodes) - { - Logger.Info("Ignoring Previously Downloaded Episodes"); - _episodeProvider.SetPreviouslyDownloadedToIgnored(); - } - } - } -} diff --git a/NzbDrone.Core/Jobs/DiskScanJob.cs b/NzbDrone.Core/Jobs/DiskScanJob.cs index e09b1896b..c5f651df9 100644 --- a/NzbDrone.Core/Jobs/DiskScanJob.cs +++ b/NzbDrone.Core/Jobs/DiskScanJob.cs @@ -15,16 +15,13 @@ namespace NzbDrone.Core.Jobs { private readonly SeriesProvider _seriesProvider; private readonly DiskScanProvider _diskScanProvider; - private readonly AutoIgnoreJob _autoIgnoreJob; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); [Inject] - public DiskScanJob(SeriesProvider seriesProvider, DiskScanProvider diskScanProvider, - AutoIgnoreJob autoIgnoreJob) + public DiskScanJob(SeriesProvider seriesProvider, DiskScanProvider diskScanProvider) { _seriesProvider = seriesProvider; _diskScanProvider = diskScanProvider; - _autoIgnoreJob = autoIgnoreJob; } public DiskScanJob() @@ -66,9 +63,6 @@ namespace NzbDrone.Core.Jobs Logger.ErrorException("An error has occurred while scanning " + series.Title, e); } } - - //Start the Auto Ignore Job - _autoIgnoreJob.Start(notification, 0 , 0); } } } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 6b1418a14..d3b987d6f 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -225,7 +225,6 @@ - diff --git a/NzbDrone.Core/Providers/DiskScanProvider.cs b/NzbDrone.Core/Providers/DiskScanProvider.cs index 15f7fb4e7..2362d14c7 100644 --- a/NzbDrone.Core/Providers/DiskScanProvider.cs +++ b/NzbDrone.Core/Providers/DiskScanProvider.cs @@ -56,8 +56,7 @@ namespace NzbDrone.Core.Providers /// Path to scan public virtual List Scan(Series series, string path) { - _mediaFileProvider.DeleteOrphaned(); - _mediaFileProvider.RepairLinks(); + _mediaFileProvider.CleanUpDatabase(); if (!_diskProvider.FolderExists(path)) { @@ -231,8 +230,11 @@ namespace NzbDrone.Core.Providers //Set the EpisodeFileId for each episode attached to this file to 0 foreach(var episode in _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId)) { - Logger.Trace("Setting EpisodeFileId for Episode: [{0}] to 0"); + Logger.Trace("Setting EpisodeFileId for Episode: [{0}] to 0", episode.EpisodeId); episode.EpisodeFileId = 0; + episode.Ignored = true; + episode.GrabDate = null; + episode.PostDownloadStatus = PostDownloadStatusType.Unknown; _episodeProvider.UpdateEpisode(episode); } diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index f347fb3d3..fcaca6cfe 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -463,13 +463,5 @@ namespace NzbDrone.Core.Providers Logger.Trace("Updating PostDownloadStatus for all episodeIds in {0}", episodeIdString); _database.Execute(episodeIdQuery); } - - /// - /// Sets Ignored to true if the episode successfully downloaded (PostDownloadStatus = 5), but EpisodeFileId = 0 - /// - public virtual void SetPreviouslyDownloadedToIgnored() - { - _database.Execute("UPDATE Episodes SET Ignored = 1, PostDownloadStatus = 0 WHERE PostDownloadStatus = 5 AND EpisodeFileId = 0"); - } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs index 5f50a978a..aab557a20 100644 --- a/NzbDrone.Core/Providers/MediaFileProvider.cs +++ b/NzbDrone.Core/Providers/MediaFileProvider.cs @@ -99,41 +99,42 @@ namespace NzbDrone.Core.Providers return new FileInfo(path); } - public virtual int RepairLinks() + public virtual void CleanUpDatabase() { - Logger.Trace("Verifying Episode>Episode file relationships."); - var updated = _database.Execute(@"UPDATE Episodes SET EpisodeFileId = 0 - WHERE EpisodeFileId IN - (SELECT Episodes.EpisodeFileId FROM Episodes - LEFT OUTER JOIN EpisodeFiles - ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId - WHERE Episodes.EpisodeFileId > 0 AND EpisodeFiles.EpisodeFileId IS null)"); + Logger.Trace("Verifying Episode > Episode file relationships."); + + string updateString = "UPDATE Episodes SET EpisodeFileId = 0, GrabDate = NULL, PostDownloadStatus = 0"; + + if (_configProvider.AutoIgnorePreviouslyDownloadedEpisodes) + { + updateString += ", Ignored = 1"; + } + + var updated = _database.Execute(updateString + + @"WHERE EpisodeFileId IN + (SELECT Episodes.EpisodeFileId FROM Episodes + LEFT OUTER JOIN EpisodeFiles + ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId + WHERE Episodes.EpisodeFileId > 0 AND EpisodeFiles.EpisodeFileId IS NULL)"); if (updated > 0) { Logger.Debug("Removed {0} invalid links to episode files.", updated); } - return updated; - } - - public virtual int DeleteOrphaned() - { Logger.Trace("Deleting orphan files."); - var updated = _database.Execute(@"DELETE FROM EpisodeFiles + updated = _database.Execute(@"DELETE FROM EpisodeFiles WHERE EpisodeFileId IN (SELECT EpisodeFiles.EpisodeFileId FROM EpisodeFiles LEFT OUTER JOIN Episodes ON EpisodeFiles.EpisodeFileId = Episodes.EpisodeFileId - WHERE Episodes.EpisodeFileId IS null)"); + WHERE Episodes.EpisodeFileId IS NULL)"); if (updated > 0) { Logger.Debug("Removed {0} orphan file(s) from database.S", updated); } - - return updated; } public virtual string GetNewFilename(IList episodes, string seriesTitle, QualityTypes quality)