mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-14 10:47:08 -07:00
decision engine now reports it's own errors rather than just dying.
This commit is contained in:
parent
9bbbc19869
commit
d6d524e624
15 changed files with 182 additions and 130 deletions
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications.Search;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
@ -18,38 +19,26 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
{
|
||||
private readonly IEnumerable<IRejectWithReason> _specifications;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DownloadDecisionMaker(IEnumerable<IRejectWithReason> specifications, IParsingService parsingService)
|
||||
public DownloadDecisionMaker(IEnumerable<IRejectWithReason> specifications, IParsingService parsingService, Logger logger)
|
||||
{
|
||||
_specifications = specifications;
|
||||
_parsingService = parsingService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<DownloadDecision> GetRssDecision(IEnumerable<ReportInfo> reports)
|
||||
{
|
||||
return GetDecisions(reports, GetGeneralRejectionReasons).ToList();
|
||||
return GetDecisions(reports).ToList();
|
||||
}
|
||||
|
||||
public List<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase)
|
||||
{
|
||||
return GetDecisions(reports, remoteEpisode =>
|
||||
{
|
||||
var generalReasons = GetGeneralRejectionReasons(remoteEpisode);
|
||||
var searchReasons = GetSearchRejectionReasons(remoteEpisode, searchDefinitionBase);
|
||||
return generalReasons.Union(searchReasons);
|
||||
}).ToList();
|
||||
return GetDecisions(reports).ToList();
|
||||
}
|
||||
|
||||
|
||||
private IEnumerable<string> GetGeneralRejectionReasons(RemoteEpisode report)
|
||||
{
|
||||
return _specifications
|
||||
.OfType<IDecisionEngineSpecification>()
|
||||
.Where(spec => !spec.IsSatisfiedBy(report))
|
||||
.Select(spec => spec.RejectionReason);
|
||||
}
|
||||
|
||||
private IEnumerable<DownloadDecision> GetDecisions(IEnumerable<ReportInfo> reports, Func<RemoteEpisode, IEnumerable<string>> decisionCallback)
|
||||
private IEnumerable<DownloadDecision> GetDecisions(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinition = null)
|
||||
{
|
||||
foreach (var report in reports)
|
||||
{
|
||||
|
@ -62,7 +51,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
|
||||
if (remoteEpisode.Series != null)
|
||||
{
|
||||
yield return new DownloadDecision(remoteEpisode, decisionCallback(remoteEpisode).ToArray());
|
||||
yield return GetDecisionForReport(remoteEpisode, searchDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -72,12 +61,40 @@ namespace NzbDrone.Core.DecisionEngine
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetSearchRejectionReasons(RemoteEpisode report, SearchDefinitionBase searchDefinitionBase)
|
||||
private DownloadDecision GetDecisionForReport(RemoteEpisode remoteEpisode, SearchDefinitionBase searchDefinition = null)
|
||||
{
|
||||
return _specifications
|
||||
.OfType<IDecisionEngineSearchSpecification>()
|
||||
.Where(spec => !spec.IsSatisfiedBy(report, searchDefinitionBase))
|
||||
.Select(spec => spec.RejectionReason);
|
||||
var reasons = _specifications.Select(c => EvaluateSpec(c, remoteEpisode, searchDefinition))
|
||||
.Where(c => !string.IsNullOrWhiteSpace(c));
|
||||
|
||||
return new DownloadDecision(remoteEpisode, reasons.ToArray());
|
||||
}
|
||||
|
||||
private string EvaluateSpec(IRejectWithReason spec, RemoteEpisode remoteEpisode, SearchDefinitionBase searchDefinitionBase = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var searchSpecification = spec as IDecisionEngineSearchSpecification;
|
||||
if (searchSpecification != null && searchDefinitionBase != null)
|
||||
{
|
||||
if (!searchSpecification.IsSatisfiedBy(remoteEpisode, searchDefinitionBase))
|
||||
{
|
||||
return spec.RejectionReason;
|
||||
}
|
||||
}
|
||||
|
||||
var generalSpecification = spec as IDecisionEngineSpecification;
|
||||
if (generalSpecification != null && !generalSpecification.IsSatisfiedBy(remoteEpisode))
|
||||
{
|
||||
return spec.RejectionReason;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorException("Couldn't evaluate decision", e);
|
||||
return string.Format("{0}: {1}", spec.GetType().Name, e.Message);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class SingleEpisodeMatchSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SingleEpisodeMatchSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string RejectionReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Episode doesn't match";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchDefinitionBase searchDefinitionBase)
|
||||
{
|
||||
var singleEpisodeSpec = searchDefinitionBase as SingleEpisodeSearchDefinition;
|
||||
if (singleEpisodeSpec == null) return true;
|
||||
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||
{
|
||||
_logger.Trace("Season number does not match searched season number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!remoteEpisode.Episodes.Select(c => c.EpisodeNumber).Contains(singleEpisodeSpec.EpisodeNumber))
|
||||
{
|
||||
_logger.Trace("Episode number does not match searched episode number, skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue