SeriesProvider gets QualityProfile in single call to DB.

SeriesProvider.GetAllSeriesWithEpisodeCount gets seasonCount(with or without specials), total episode count & episodeWithFile count (excluding ignored episodes).
Added tests for SeriesWithEpisodeCount.
pull/4/head
Mark McDowall 13 years ago
parent 5a99d374d9
commit 431d850d32

@ -65,11 +65,13 @@ namespace NzbDrone.Core.Test
mocker.GetMock<ConfigProvider>()
.Setup(c => c.UseSeasonFolder).Returns(useSeasonFolder);
mocker.SetConstant(MockLib.GetEmptyDatabase());
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeProfiles = Builder<QualityProfile>.CreateListOfSize(2).Build();
db.InsertMany(fakeProfiles);
const string path = "C:\\Test\\";
const int tvDbId = 1234;
const int qualityProfileId = 2;
@ -78,8 +80,6 @@ namespace NzbDrone.Core.Test
var seriesProvider = mocker.Resolve<SeriesProvider>();
seriesProvider.AddSeries(path, tvDbId, qualityProfileId);
//Assert
var series = seriesProvider.GetAllSeries();
series.Should().HaveCount(1);
@ -104,7 +104,6 @@ namespace NzbDrone.Core.Test
Assert.IsNull(series);
}
[Test]
[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Sequence contains no elements")]
public void Get_series_invalid_series_id_should_return_null()
@ -233,6 +232,7 @@ namespace NzbDrone.Core.Test
.With(c => c.SeriesId = 11)
.Build());
db.InsertMany(Builder<QualityProfile>.CreateListOfSize(3).Build());
//Act, Assert
var provider = mocker.Resolve<SeriesProvider>();
@ -240,5 +240,134 @@ namespace NzbDrone.Core.Test
Assert.IsFalse(provider.IsMonitored(11));
Assert.IsFalse(provider.IsMonitored(1));
}
[Test]
public void Get_Series_With_Count()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateNew().With(e => e.QualityProfileId = fakeQuality.QualityProfileId).Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10).WhereAll().Have(e => e.SeriesId = fakeSeries.SeriesId).Have(e => e.Ignored = false).WhereRandom(5).Have(e => e.EpisodeFileId = 0).Build();
db.Insert(fakeSeries);
db.Insert(fakeQuality);
db.InsertMany(fakeEpisodes);
//Act
mocker.Resolve<QualityProvider>();
var series = mocker.Resolve<SeriesProvider>().GetAllSeriesWithEpisodeCount(true);
//Assert
series.Should().HaveCount(1);
Assert.AreEqual(10, series[0].EpisodeCount);
Assert.AreEqual(5, series[0].EpisodeFileCount);
}
[Test]
public void Get_Series_With_Count_AllIgnored()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateNew().With(e => e.QualityProfileId = fakeQuality.QualityProfileId).Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10).WhereAll().Have(e => e.SeriesId = fakeSeries.SeriesId).Have(e => e.Ignored = true).WhereRandom(5).Have(e => e.EpisodeFileId = 0).Build();
db.Insert(fakeSeries);
db.Insert(fakeQuality);
db.InsertMany(fakeEpisodes);
//Act
mocker.Resolve<QualityProvider>();
var series = mocker.Resolve<SeriesProvider>().GetAllSeriesWithEpisodeCount(true);
//Assert
series.Should().HaveCount(1);
Assert.AreEqual(0, series[0].EpisodeCount);
Assert.AreEqual(0, series[0].EpisodeFileCount);
}
[Test]
public void Get_Series_With_Count_AllDownloaded()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateNew().With(e => e.QualityProfileId = fakeQuality.QualityProfileId).Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10).WhereAll().Have(e => e.SeriesId = fakeSeries.SeriesId).Have(e => e.Ignored = false).Build();
db.Insert(fakeSeries);
db.Insert(fakeQuality);
db.InsertMany(fakeEpisodes);
//Act
mocker.Resolve<QualityProvider>();
var series = mocker.Resolve<SeriesProvider>().GetAllSeriesWithEpisodeCount(true);
//Assert
series.Should().HaveCount(1);
Assert.AreEqual(10, series[0].EpisodeCount);
Assert.AreEqual(10, series[0].EpisodeFileCount);
}
[Test]
public void Get_Series_With_Count_Half_Ignored()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateNew().With(e => e.QualityProfileId = fakeQuality.QualityProfileId).Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll().Have(e => e.SeriesId = fakeSeries.SeriesId)
.WhereTheFirst(5).Have(e => e.Ignored = false)
.WhereTheLast(5).Have(e => e.Ignored = true)
.Build();
db.Insert(fakeSeries);
db.Insert(fakeQuality);
db.InsertMany(fakeEpisodes);
//Act
mocker.Resolve<QualityProvider>();
var series = mocker.Resolve<SeriesProvider>().GetAllSeriesWithEpisodeCount(true);
//Assert
series.Should().HaveCount(1);
Assert.AreEqual(5, series[0].EpisodeCount);
Assert.AreEqual(5, series[0].EpisodeFileCount);
}
[Test]
public void Get_Single_Series()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeQuality = Builder<QualityProfile>.CreateNew().Build();
var fakeSeries = Builder<Series>.CreateNew()
.With(e => e.QualityProfileId = fakeQuality.QualityProfileId)
.With(e => e.SeriesId = 1)
.Build();
db.Insert(fakeSeries);
db.Insert(fakeQuality);
//Act
mocker.Resolve<QualityProvider>();
var series = mocker.Resolve<SeriesProvider>().GetSeries(1);
//Assert
series.QualityProfile.Should().NotBeNull();
series.QualityProfileId.Should().Be(fakeQuality.QualityProfileId);
}
}
}

@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using PetaPoco;
using TvdbLib.Data;
@ -17,17 +18,15 @@ namespace NzbDrone.Core.Providers
private readonly ConfigProvider _configProvider;
private readonly TvDbProvider _tvDbProvider;
private readonly IDatabase _database;
private readonly QualityProvider _qualityProvider;
private readonly SceneMappingProvider _sceneNameMappingProvider;
private static readonly Regex TimeRegex = new Regex(@"^(?<time>\d+:?\d*)\W*(?<meridiem>am|pm)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public SeriesProvider(IDatabase database, ConfigProvider configProviderProvider, QualityProvider qualityProvider,
public SeriesProvider(IDatabase database, ConfigProvider configProviderProvider,
TvDbProvider tvDbProviderProvider, SceneMappingProvider sceneNameMappingProvider)
{
_database = database;
_configProvider = configProviderProvider;
_tvDbProvider = tvDbProviderProvider;
_qualityProvider = qualityProvider;
_sceneNameMappingProvider = sceneNameMappingProvider;
}
@ -37,15 +36,36 @@ namespace NzbDrone.Core.Providers
public virtual IList<Series> GetAllSeries()
{
var series = _database.Fetch<Series>();
series.ForEach(c => c.QualityProfile = _qualityProvider.Get(c.QualityProfileId));
var series = _database.Fetch<Series, QualityProfile>(@"SELECT * FROM Series
INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId");
return series;
}
public virtual IList<Series> GetAllSeriesWithEpisodeCount(bool ignoreSpecials)
{
var seasonNumber = 0;
if (!ignoreSpecials)
seasonNumber = -1;
var series = _database.Fetch<Series, QualityProfile>(@"SELECT Series.*, COUNT (NULLIF(Ignored, 1)) AS EpisodeCount,
SUM(CASE WHEN Ignored = 0 AND EpisodeFileId > 0 THEN 1 ELSE 0 END) as EpisodeFileCount,
COUNT (DISTINCT(NULLIF(SeasonNumber, @0))) as SeasonCount,
QualityProfiles.*
FROM Series
INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId
JOIN Episodes ON Series.SeriesId = Episodes.SeriesId
GROUP BY seriesId", seasonNumber);
return series;
}
public virtual Series GetSeries(int seriesId)
{
var series = _database.Single<Series>("WHERE seriesId= @0", seriesId);
series.QualityProfile = _qualityProvider.Get(series.QualityProfileId);
var series = _database.Fetch<Series, QualityProfile>(@"SELECT * FROM Series
INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId
WHERE seriesId= @0", seriesId).Single();
return series;
}
@ -117,15 +137,11 @@ namespace NzbDrone.Core.Providers
return GetSeries(seriesId.Value);
}
var series = _database.FirstOrDefault<Series>("WHERE CleanTitle = @0", normalizeTitle);
if (series != null)
{
series.QualityProfile = _qualityProvider.Get(series.QualityProfileId);
return series;
}
var series = _database.Fetch<Series, QualityProfile>(@"SELECT * FROM Series
INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId
WHERE CleanTitle = @0", normalizeTitle).FirstOrDefault();
return null;
return series;
}
public virtual void UpdateSeries(Series series)

@ -10,32 +10,25 @@ namespace NzbDrone.Core.Repository
{
public virtual int SeriesId { get; set; }
public string Title { get; set; }
public string CleanTitle { get; set; }
public string Status { get; set; }
public string Overview { get; set; }
[DisplayName("Air on")]
public DayOfWeek? AirsDayOfWeek { get; set; }
public String AirTimes { get; set; }
public string Language { get; set; }
public string Path { get; set; }
public bool Monitored { get; set; }
public virtual int QualityProfileId { get; set; }
public bool SeasonFolder { get; set; }
@ -55,5 +48,14 @@ namespace NzbDrone.Core.Repository
[Ignore]
public QualityProfile QualityProfile { get; set; }
[ResultColumn]
public int EpisodeCount { get; set; }
[ResultColumn]
public int EpisodeFileCount { get; set; }
[ResultColumn]
public int SeasonCount { get; set; }
}
}

@ -80,8 +80,7 @@ namespace NzbDrone.Web.Controllers
[GridAction]
public ActionResult _AjaxSeriesGrid()
{
var series = GetSeriesModels(_seriesProvider.GetAllSeries().ToList());
var series = GetSeriesModels(_seriesProvider.GetAllSeriesWithEpisodeCount(true).ToList());
return View(new GridModel(series));
}
@ -124,17 +123,6 @@ namespace NzbDrone.Web.Controllers
return View(new GridModel(episodes));
}
public JsonResult GetEpisodeCount(int seriesId)
{
var count = _mediaFileProvider.GetEpisodeFilesCount(seriesId);
return Json(new
{
Episodes = count.Item1,
EpisodeTotal = count.Item2
}, JsonRequestBehavior.AllowGet);
}
public ActionResult SearchForSeries(string seriesName)
{
var model = new List<SeriesSearchResultModel>();
@ -206,25 +194,22 @@ namespace NzbDrone.Web.Controllers
private List<SeriesModel> GetSeriesModels(List<Series> seriesInDb)
{
var series = new List<SeriesModel>();
foreach (var s in seriesInDb)
{
series.Add(new SeriesModel
{
SeriesId = s.SeriesId,
Title = s.Title,
AirsDayOfWeek = s.AirsDayOfWeek.ToString(),
Monitored = s.Monitored,
Overview = s.Overview,
Path = s.Path,
QualityProfileId = s.QualityProfileId,
QualityProfileName = s.QualityProfile.Name,
SeasonFolder = s.SeasonFolder,
Status = s.Status,
SeasonsCount = _episodeProvider.GetSeasons(s.SeriesId).Where(n => n != 0).Count()
});
}
var series = seriesInDb.Select(s => new SeriesModel
{
SeriesId = s.SeriesId,
Title = s.Title,
AirsDayOfWeek = s.AirsDayOfWeek.ToString(),
Monitored = s.Monitored,
Overview = s.Overview,
Path = s.Path,
QualityProfileId = s.QualityProfileId,
QualityProfileName = s.QualityProfile.Name,
SeasonFolder = s.SeasonFolder,
Status = s.Status,
SeasonsCount = s.SeasonCount,
EpisodeCount = s.EpisodeCount,
EpisodeFileCount = s.EpisodeFileCount
}).ToList();
return series;
}

@ -14,6 +14,8 @@ namespace NzbDrone.Web.Models
//View Only
public string Title { get; set; }
public int SeasonsCount { get; set; }
public int EpisodeCount { get; set; }
public int EpisodeFileCount { get; set; }
public string Status { get; set; }
public string AirsDayOfWeek { get; set; }
public string QualityProfileName { get; set; }

@ -186,37 +186,9 @@
function grid_rowBound(e) {
var dataItem = e.dataItem;
var seriesId = dataItem.SeriesId;
var getEpisodeCountUrl = '@Url.Action("GetEpisodeCount", "Series")';
var episodeCount = dataItem.EpisodeCount;
var episodeFileCount = dataItem.EpisodeFileCount;
$("#progressbar_" + seriesId).episodeProgress(0, 0);
$.ajax({
type: "GET",
url: getEpisodeCountUrl,
data: jQuery.param({ seriesId: seriesId }),
error: function (req, status, error) {
alert("Sorry! We could search for " + id + " at this time. " + error);
},
success: function (data, textStatus, jqXHR) {
var episodes = data.Episodes;
var episodeTotal = data.EpisodeTotal;
var counter = 0;
var max = episodes + 1;
$.doTimeout(10, function () {
if (counter >= max) {
$("#progressbar_" + seriesId).episodeProgress(episodes, episodeTotal);
return false;
}
$("#progressbar_" + seriesId).episodeProgress(counter, episodeTotal);
counter += 5;
return true;
});
}
});
$("#progressbar_" + seriesId).episodeProgress(episodeFileCount, episodeCount);
}
</script>
Loading…
Cancel
Save