mirror of https://github.com/Sonarr/Sonarr
Fixed: Errors loading queue after episodes in series are removed
Closes #3565
This commit is contained in:
parent
54a267d860
commit
6c324c8a1c
|
@ -11,6 +11,7 @@ using NzbDrone.Core.Test.Framework;
|
|||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
||||
{
|
||||
|
@ -144,5 +145,185 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
|||
trackedDownload.RemoteEpisode.ParsedEpisodeInfo.SeasonNumber.Should().Be(0);
|
||||
trackedDownload.RemoteEpisode.MappedSeasonNumber.Should().Be(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_unmap_tracked_download_if_episode_deleted()
|
||||
{
|
||||
GivenDownloadHistory();
|
||||
|
||||
var remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Series = new Series() { Id = 5 },
|
||||
Episodes = new List<Episode> { new Episode { Id = 4 } },
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo()
|
||||
{
|
||||
SeriesTitle = "TV Series",
|
||||
SeasonNumber = 1,
|
||||
EpisodeNumbers = new[] { 1 }
|
||||
},
|
||||
MappedSeasonNumber = 0
|
||||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Returns(remoteEpisode);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.FindByDownloadId(It.IsAny<string>()))
|
||||
.Returns(new List<EpisodeHistory>());
|
||||
|
||||
|
||||
var client = new DownloadClientDefinition()
|
||||
{
|
||||
Id = 1,
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
};
|
||||
|
||||
var item = new DownloadClientItem()
|
||||
{
|
||||
Title = "TV Series - S01E01",
|
||||
DownloadId = "12345",
|
||||
DownloadClientInfo = new DownloadClientItemClientInfo
|
||||
{
|
||||
Id = 1,
|
||||
Type = "Blackhole",
|
||||
Name = "Blackhole Client",
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
}
|
||||
};
|
||||
|
||||
Subject.TrackDownload(client, item);
|
||||
Subject.GetTrackedDownloads().Should().HaveCount(1);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Subject.Handle(new EpisodeInfoRefreshedEvent(remoteEpisode.Series, new List<Episode>(), new List<Episode>(), remoteEpisode.Episodes));
|
||||
|
||||
var trackedDownloads = Subject.GetTrackedDownloads();
|
||||
trackedDownloads.Should().HaveCount(1);
|
||||
trackedDownloads.First().RemoteEpisode.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_throw_when_processing_deleted_episodes()
|
||||
{
|
||||
GivenDownloadHistory();
|
||||
|
||||
var remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Series = new Series() { Id = 5 },
|
||||
Episodes = new List<Episode> { new Episode { Id = 4 } },
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo()
|
||||
{
|
||||
SeriesTitle = "TV Series",
|
||||
SeasonNumber = 1,
|
||||
EpisodeNumbers = new[] { 1 }
|
||||
},
|
||||
MappedSeasonNumber = 0
|
||||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.FindByDownloadId(It.IsAny<string>()))
|
||||
.Returns(new List<EpisodeHistory>());
|
||||
|
||||
|
||||
var client = new DownloadClientDefinition()
|
||||
{
|
||||
Id = 1,
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
};
|
||||
|
||||
var item = new DownloadClientItem()
|
||||
{
|
||||
Title = "TV Series - S01E01",
|
||||
DownloadId = "12345",
|
||||
DownloadClientInfo = new DownloadClientItemClientInfo
|
||||
{
|
||||
Id = 1,
|
||||
Type = "Blackhole",
|
||||
Name = "Blackhole Client",
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
}
|
||||
};
|
||||
|
||||
Subject.TrackDownload(client, item);
|
||||
Subject.GetTrackedDownloads().Should().HaveCount(1);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Subject.Handle(new EpisodeInfoRefreshedEvent(remoteEpisode.Series, new List<Episode>(), new List<Episode>(), remoteEpisode.Episodes));
|
||||
|
||||
var trackedDownloads = Subject.GetTrackedDownloads();
|
||||
trackedDownloads.Should().HaveCount(1);
|
||||
trackedDownloads.First().RemoteEpisode.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_throw_when_processing_deleted_series()
|
||||
{
|
||||
GivenDownloadHistory();
|
||||
|
||||
var remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Series = new Series() { Id = 5 },
|
||||
Episodes = new List<Episode> { new Episode { Id = 4 } },
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo()
|
||||
{
|
||||
SeriesTitle = "TV Series",
|
||||
SeasonNumber = 1,
|
||||
EpisodeNumbers = new[] { 1 }
|
||||
},
|
||||
MappedSeasonNumber = 0
|
||||
};
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.FindByDownloadId(It.IsAny<string>()))
|
||||
.Returns(new List<EpisodeHistory>());
|
||||
|
||||
|
||||
var client = new DownloadClientDefinition()
|
||||
{
|
||||
Id = 1,
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
};
|
||||
|
||||
var item = new DownloadClientItem()
|
||||
{
|
||||
Title = "TV Series - S01E01",
|
||||
DownloadId = "12345",
|
||||
DownloadClientInfo = new DownloadClientItemClientInfo
|
||||
{
|
||||
Id = 1,
|
||||
Type = "Blackhole",
|
||||
Name = "Blackhole Client",
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
}
|
||||
};
|
||||
|
||||
Subject.TrackDownload(client, item);
|
||||
Subject.GetTrackedDownloads().Should().HaveCount(1);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.Map(It.IsAny<ParsedEpisodeInfo>(), It.IsAny<int>(), It.IsAny<int>(), null))
|
||||
.Returns(default(RemoteEpisode));
|
||||
|
||||
Subject.Handle(new SeriesDeletedEvent(remoteEpisode.Series, true, true));
|
||||
|
||||
var trackedDownloads = Subject.GetTrackedDownloads();
|
||||
trackedDownloads.Should().HaveCount(1);
|
||||
trackedDownloads.First().RemoteEpisode.Should().BeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ using NzbDrone.Core.Download.History;
|
|||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.Download.TrackedDownloads
|
||||
{
|
||||
|
@ -21,7 +22,9 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
void UpdateTrackable(List<TrackedDownload> trackedDownloads);
|
||||
}
|
||||
|
||||
public class TrackedDownloadService : ITrackedDownloadService
|
||||
public class TrackedDownloadService : ITrackedDownloadService,
|
||||
IHandle<EpisodeInfoRefreshedEvent>,
|
||||
IHandle<SeriesDeletedEvent>
|
||||
{
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly IHistoryService _historyService;
|
||||
|
@ -187,6 +190,13 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateCachedItem(TrackedDownload trackedDownload)
|
||||
{
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(trackedDownload.DownloadItem.Title);
|
||||
|
||||
trackedDownload.RemoteEpisode = parsedEpisodeInfo == null ? null :_parsingService.Map(parsedEpisodeInfo, 0, 0);
|
||||
}
|
||||
|
||||
private static TrackedDownloadState GetStateFromHistory(DownloadHistoryEventType eventType)
|
||||
{
|
||||
switch (eventType)
|
||||
|
@ -201,5 +211,45 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
return TrackedDownloadState.Downloading;
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(EpisodeInfoRefreshedEvent message)
|
||||
{
|
||||
var needsToUpdate = false;
|
||||
|
||||
foreach (var episode in message.Removed)
|
||||
{
|
||||
var cachedItems = _cache.Values.Where(t =>
|
||||
t.RemoteEpisode?.Episodes != null &&
|
||||
t.RemoteEpisode.Episodes.Any(e => e.Id == episode.Id))
|
||||
.ToList();
|
||||
|
||||
if (cachedItems.Any())
|
||||
{
|
||||
needsToUpdate = true;
|
||||
}
|
||||
|
||||
cachedItems.ForEach(UpdateCachedItem);
|
||||
}
|
||||
|
||||
if (needsToUpdate)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new TrackedDownloadRefreshedEvent(GetTrackedDownloads()));
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SeriesDeletedEvent message)
|
||||
{
|
||||
var cachedItems = _cache.Values.Where(t =>
|
||||
t.RemoteEpisode?.Series != null &&
|
||||
t.RemoteEpisode.Series.Id == message.Series.Id)
|
||||
.ToList();
|
||||
|
||||
if (cachedItems.Any())
|
||||
{
|
||||
cachedItems.ForEach(UpdateCachedItem);
|
||||
|
||||
_eventAggregator.PublishEvent(new TrackedDownloadRefreshedEvent(GetTrackedDownloads()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,13 @@ namespace NzbDrone.Core.Tv.Events
|
|||
public Series Series { get; set; }
|
||||
public ReadOnlyCollection<Episode> Added { get; private set; }
|
||||
public ReadOnlyCollection<Episode> Updated { get; private set; }
|
||||
public ReadOnlyCollection<Episode> Removed { get; private set; }
|
||||
|
||||
public EpisodeInfoRefreshedEvent(Series series, IList<Episode> added, IList<Episode> updated)
|
||||
public EpisodeInfoRefreshedEvent(Series series, IList<Episode> added, IList<Episode> updated, IList<Episode> removed)
|
||||
{
|
||||
Series = series;
|
||||
Added = new ReadOnlyCollection<Episode>(added);
|
||||
Updated = new ReadOnlyCollection<Episode>(updated);
|
||||
Removed = new ReadOnlyCollection<Episode>(removed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -99,7 +99,7 @@ namespace NzbDrone.Core.Tv
|
|||
_episodeService.UpdateMany(updateList);
|
||||
_episodeService.InsertMany(newList);
|
||||
|
||||
_eventAggregator.PublishEvent(new EpisodeInfoRefreshedEvent(series, newList, updateList));
|
||||
_eventAggregator.PublishEvent(new EpisodeInfoRefreshedEvent(series, newList, updateList, existingEpisodes));
|
||||
|
||||
if (failCount != 0)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue