From 9e5353aaccf65f45b5f97729b309da39ed592dbe Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 28 Aug 2013 18:43:45 -0700 Subject: [PATCH] Cleanup orphaned seasons when deleting episodes --- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 1 + .../HandleEpisodeInfoDeletedEventFixture.cs | 93 ++++++++++++++++++ NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Tv/Events/EpisodeInfoDeletedEvent.cs | 16 +++ NzbDrone.Core/Tv/RefreshEpisodeService.cs | 14 ++- NzbDrone.Core/Tv/SeasonService.cs | Bin 8572 -> 9871 bytes 6 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs create mode 100644 NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index b3e34350c..0d3bd3634 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -186,6 +186,7 @@ + diff --git a/NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs b/NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs new file mode 100644 index 000000000..d31c2b679 --- /dev/null +++ b/NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FizzWare.NBuilder; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; +using NzbDrone.Core.Tv.Events; + +namespace NzbDrone.Core.Test.TvTests.SeasonServiceTests +{ + [TestFixture] + public class HandleEpisodeInfoDeletedEventFixture : CoreTest + { + private List _seasons; + private List _episodes; + + [SetUp] + public void Setup() + { + _seasons = Builder + .CreateListOfSize(1) + .All() + .With(s => s.SeriesId = 1) + .Build() + .ToList(); + + _episodes = Builder + .CreateListOfSize(1) + .All() + .With(e => e.SeasonNumber = _seasons.First().SeasonNumber) + .With(s => s.SeriesId = _seasons.First().SeasonNumber) + .Build() + .ToList(); + + Mocker.GetMock() + .Setup(s => s.GetSeasonBySeries(It.IsAny())) + .Returns(_seasons); + + Mocker.GetMock() + .Setup(s => s.GetEpisodesBySeason(It.IsAny(), _seasons.First().SeasonNumber)) + .Returns(_episodes); + } + + private void GivenAbandonedSeason() + { + Mocker.GetMock() + .Setup(s => s.GetEpisodesBySeason(It.IsAny(), _seasons.First().SeasonNumber)) + .Returns(new List()); + } + + [Test] + public void should_not_delete_when_season_is_still_valid() + { + Subject.Handle(new EpisodeInfoDeletedEvent(_episodes)); + + Mocker.GetMock() + .Verify(v => v.Delete(It.IsAny()), Times.Never()); + } + + [Test] + public void should_delete_season_if_no_episodes_exist_in_that_season() + { + GivenAbandonedSeason(); + + Subject.Handle(new EpisodeInfoDeletedEvent(_episodes)); + + Mocker.GetMock() + .Verify(v => v.Delete(It.IsAny()), Times.Once()); + } + + [Test] + public void should_only_delete_a_season_once() + { + _episodes = Builder + .CreateListOfSize(5) + .All() + .With(e => e.SeasonNumber = _seasons.First().SeasonNumber) + .With(s => s.SeriesId = _seasons.First().SeasonNumber) + .Build() + .ToList(); + + GivenAbandonedSeason(); + + Subject.Handle(new EpisodeInfoDeletedEvent(_episodes)); + + Mocker.GetMock() + .Verify(v => v.Delete(It.IsAny()), Times.Once()); + } + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a774cc3fd..9ed55a6ff 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -350,6 +350,7 @@ + diff --git a/NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs b/NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs new file mode 100644 index 000000000..864445e58 --- /dev/null +++ b/NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.Tv.Events +{ + public class EpisodeInfoDeletedEvent : IEvent + { + public ReadOnlyCollection Episodes { get; private set; } + + public EpisodeInfoDeletedEvent(IList episodes) + { + Episodes = new ReadOnlyCollection(episodes); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Tv/RefreshEpisodeService.cs b/NzbDrone.Core/Tv/RefreshEpisodeService.cs index 14140ba84..c62d8a5d2 100644 --- a/NzbDrone.Core/Tv/RefreshEpisodeService.cs +++ b/NzbDrone.Core/Tv/RefreshEpisodeService.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Core.Tv var successCount = 0; var failCount = 0; - var existinEpisodes = _episodeService.GetEpisodeBySeries(series.Id); + var existingEpisodes = _episodeService.GetEpisodeBySeries(series.Id); var seasons = _seasonService.GetSeasonsBySeries(series.Id); var updateList = new List(); @@ -44,11 +44,11 @@ namespace NzbDrone.Core.Tv { try { - var episodeToUpdate = existinEpisodes.SingleOrDefault(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber); + var episodeToUpdate = existingEpisodes.SingleOrDefault(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber); if (episodeToUpdate != null) { - existinEpisodes.Remove(episodeToUpdate); + existingEpisodes.Remove(episodeToUpdate); updateList.Add(episodeToUpdate); } else @@ -82,11 +82,10 @@ namespace NzbDrone.Core.Tv AdjustMultiEpisodeAirTime(series, allEpisodes); - _episodeService.DeleteMany(existinEpisodes); + _episodeService.DeleteMany(existingEpisodes); _episodeService.UpdateMany(updateList); _episodeService.InsertMany(newList); - if (newList.Any()) { _messageAggregator.PublishEvent(new EpisodeInfoAddedEvent(newList, series)); @@ -97,6 +96,11 @@ namespace NzbDrone.Core.Tv _messageAggregator.PublishEvent(new EpisodeInfoUpdatedEvent(updateList)); } + if (existingEpisodes.Any()) + { + _messageAggregator.PublishEvent(new EpisodeInfoDeletedEvent(updateList)); + } + if (failCount != 0) { _logger.Info("Finished episode refresh for series: {0}. Successful: {1} - Failed: {2} ", diff --git a/NzbDrone.Core/Tv/SeasonService.cs b/NzbDrone.Core/Tv/SeasonService.cs index 8cb3d0c75795638537f01c86fdb483b545701f5e..6355796a47cb4e1da5460d78e1594785dad261cc 100644 GIT binary patch delta 586 zcmZ`$O-tNR6ooWuVm@A;bY^Om_O+YNSQ${)V^JJR7uLa9xGbr;Qy;_^O)>!mS8hZE zh4UlamBLWyZ|Gm>raPB*;ie$1$;?#5wr};g=iGD7z4vfcls1P6miGo3stLuC zk~hKZUt0Z)wfd6UtJZ4p%<}E>*JDA1py4o*Cyf93s& z$+4jfT=Nl3i($kn!?p~3=TGt5v2pBN;L;k!l~d7+i-Wl{?!B|Ua_0+9?}{I>8zzy! Ao&W#< delta 98 zcmeD8{o}MDjcGC~v+(3eOk!aA3X{ZUPv*^Blk0fcCfA6GPwp3ezWEPt9@FFkCYH&$ h!s1}MQ9uh!uNF`T)0YI4!1Nb^La0XW%|ha}`~Y6UASM6+