mirror of https://github.com/Sonarr/Sonarr
Refactored PendingRelease logic for performance.
This commit is contained in:
parent
5b0e959d3f
commit
70afacee3f
|
@ -51,6 +51,34 @@ namespace NzbDrone.Common.Extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Dictionary<TKey, TItem> ToDictionaryIgnoreDuplicates<TItem, TKey>(this IEnumerable<TItem> src, Func<TItem, TKey> keySelector)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<TKey, TItem>();
|
||||||
|
foreach (var item in src)
|
||||||
|
{
|
||||||
|
var key = keySelector(item);
|
||||||
|
if (!result.ContainsKey(key))
|
||||||
|
{
|
||||||
|
result[key] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<TKey, TValue> ToDictionaryIgnoreDuplicates<TItem, TKey, TValue>(this IEnumerable<TItem> src, Func<TItem, TKey> keySelector, Func<TItem, TValue> valueSelector)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<TKey, TValue>();
|
||||||
|
foreach (var item in src)
|
||||||
|
{
|
||||||
|
var key = keySelector(item);
|
||||||
|
if (!result.ContainsKey(key))
|
||||||
|
{
|
||||||
|
result[key] = valueSelector(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static void AddIfNotNull<TSource>(this List<TSource> source, TSource item)
|
public static void AddIfNotNull<TSource>(this List<TSource> source, TSource item)
|
||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Marr.Data;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Crypto;
|
using NzbDrone.Common.Crypto;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
@ -66,35 +67,30 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Add(DownloadDecision decision, PendingReleaseReason reason)
|
public void Add(DownloadDecision decision, PendingReleaseReason reason)
|
||||||
{
|
{
|
||||||
var alreadyPending = _repository.AllBySeriesId(decision.RemoteEpisode.Series.Id);
|
AddMany(new List<Tuple<DownloadDecision, PendingReleaseReason>> { Tuple.Create(decision, reason) });
|
||||||
|
|
||||||
alreadyPending = IncludeRemoteEpisodes(alreadyPending);
|
|
||||||
|
|
||||||
Add(alreadyPending, decision, reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddMany(List<Tuple<DownloadDecision, PendingReleaseReason>> decisions)
|
public void AddMany(List<Tuple<DownloadDecision, PendingReleaseReason>> decisions)
|
||||||
{
|
{
|
||||||
var alreadyPending = decisions.Select(v => v.Item1.RemoteEpisode.Series.Id).Distinct().SelectMany(_repository.AllBySeriesId).ToList();
|
foreach (var seriesDecisions in decisions.GroupBy(v => v.Item1.RemoteEpisode.Series.Id))
|
||||||
|
|
||||||
alreadyPending = IncludeRemoteEpisodes(alreadyPending);
|
|
||||||
|
|
||||||
foreach (var pair in decisions)
|
|
||||||
{
|
{
|
||||||
Add(alreadyPending, pair.Item1, pair.Item2);
|
var series = seriesDecisions.First().Item1.RemoteEpisode.Series;
|
||||||
}
|
var alreadyPending = _repository.AllBySeriesId(series.Id);
|
||||||
}
|
|
||||||
|
|
||||||
private void Add(List<PendingRelease> alreadyPending, DownloadDecision decision, PendingReleaseReason reason)
|
alreadyPending = IncludeRemoteEpisodes(alreadyPending, seriesDecisions.ToDictionaryIgnoreDuplicates(v => v.Item1.RemoteEpisode.Release.Title, v => v.Item1.RemoteEpisode));
|
||||||
|
var alreadyPendingByEpisode = CreateEpisodeLookup(alreadyPending);
|
||||||
|
|
||||||
|
foreach (var pair in seriesDecisions)
|
||||||
{
|
{
|
||||||
|
var decision = pair.Item1;
|
||||||
|
var reason = pair.Item2;
|
||||||
|
|
||||||
var episodeIds = decision.RemoteEpisode.Episodes.Select(e => e.Id);
|
var episodeIds = decision.RemoteEpisode.Episodes.Select(e => e.Id);
|
||||||
|
|
||||||
var existingReports = alreadyPending.Where(r => r.RemoteEpisode.Episodes.Select(e => e.Id)
|
var existingReports = episodeIds.SelectMany(v => alreadyPendingByEpisode[v] ?? Enumerable.Empty<PendingRelease>())
|
||||||
.Intersect(episodeIds)
|
.Distinct().ToList();
|
||||||
.Any());
|
|
||||||
|
|
||||||
var matchingReports = existingReports.Where(MatchingReleasePredicate(decision.RemoteEpisode.Release)).ToList();
|
var matchingReports = existingReports.Where(MatchingReleasePredicate(decision.RemoteEpisode.Release)).ToList();
|
||||||
|
|
||||||
|
@ -121,15 +117,25 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
{
|
{
|
||||||
_repository.Delete(duplicate.Id);
|
_repository.Delete(duplicate.Id);
|
||||||
alreadyPending.Remove(duplicate);
|
alreadyPending.Remove(duplicate);
|
||||||
|
alreadyPendingByEpisode = CreateEpisodeLookup(alreadyPending);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Adding release {0} to pending releases with reason {1}", decision.RemoteEpisode, reason);
|
_logger.Debug("Adding release {0} to pending releases with reason {1}", decision.RemoteEpisode, reason);
|
||||||
Insert(decision, reason);
|
Insert(decision, reason);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ILookup<int, PendingRelease> CreateEpisodeLookup(IEnumerable<PendingRelease> alreadyPending)
|
||||||
|
{
|
||||||
|
return alreadyPending.SelectMany(v => v.RemoteEpisode.Episodes
|
||||||
|
.Select(d => new { Episode = d, PendingRelease = v }))
|
||||||
|
.ToLookup(v => v.Episode.Id, v => v.PendingRelease);
|
||||||
|
}
|
||||||
|
|
||||||
public List<ReleaseInfo> GetPending()
|
public List<ReleaseInfo> GetPending()
|
||||||
{
|
{
|
||||||
|
@ -254,11 +260,27 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
return IncludeRemoteEpisodes(_repository.AllBySeriesId(seriesId).ToList());
|
return IncludeRemoteEpisodes(_repository.AllBySeriesId(seriesId).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PendingRelease> IncludeRemoteEpisodes(List<PendingRelease> releases)
|
private List<PendingRelease> IncludeRemoteEpisodes(List<PendingRelease> releases, Dictionary<string, RemoteEpisode> knownRemoteEpisodes = null)
|
||||||
{
|
{
|
||||||
var result = new List<PendingRelease>();
|
var result = new List<PendingRelease>();
|
||||||
var seriesMap = _seriesService.GetSeries(releases.Select(v => v.SeriesId).Distinct())
|
|
||||||
.ToDictionary(v => v.Id);
|
var seriesMap = new Dictionary<int, Series>();
|
||||||
|
|
||||||
|
if (knownRemoteEpisodes != null)
|
||||||
|
{
|
||||||
|
foreach (var series in knownRemoteEpisodes.Values.Select(v => v.Series))
|
||||||
|
{
|
||||||
|
if (!seriesMap.ContainsKey(series.Id))
|
||||||
|
{
|
||||||
|
seriesMap[series.Id] = series;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var series in _seriesService.GetSeries(releases.Select(v => v.SeriesId).Distinct().Where(v => !seriesMap.ContainsKey(v))))
|
||||||
|
{
|
||||||
|
seriesMap[series.Id] = series;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var release in releases)
|
foreach (var release in releases)
|
||||||
{
|
{
|
||||||
|
@ -267,7 +289,17 @@ namespace NzbDrone.Core.Download.Pending
|
||||||
// Just in case the series was removed, but wasn't cleaned up yet (housekeeper will clean it up)
|
// Just in case the series was removed, but wasn't cleaned up yet (housekeeper will clean it up)
|
||||||
if (series == null) return null;
|
if (series == null) return null;
|
||||||
|
|
||||||
var episodes = _parsingService.GetEpisodes(release.ParsedEpisodeInfo, series, true);
|
List<Episode> episodes;
|
||||||
|
|
||||||
|
RemoteEpisode knownRemoteEpisode;
|
||||||
|
if (knownRemoteEpisodes != null && knownRemoteEpisodes.TryGetValue(release.Release.Title, out knownRemoteEpisode))
|
||||||
|
{
|
||||||
|
episodes = knownRemoteEpisode.Episodes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
episodes = _parsingService.GetEpisodes(release.ParsedEpisodeInfo, series, true);
|
||||||
|
}
|
||||||
|
|
||||||
release.RemoteEpisode = new RemoteEpisode
|
release.RemoteEpisode = new RemoteEpisode
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue