Fixed: Quality Profiles resetting Custom Format scores during housekeeping
Closes #5359
This commit is contained in:
parent
2c004e1f96
commit
4b4301a076
|
@ -41,13 +41,11 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
new ProfileFormatItem
|
new ProfileFormatItem
|
||||||
{
|
{
|
||||||
Id = 1,
|
|
||||||
Format = _customFormatOne,
|
Format = _customFormatOne,
|
||||||
Score = 50
|
Score = 50
|
||||||
},
|
},
|
||||||
new ProfileFormatItem
|
new ProfileFormatItem
|
||||||
{
|
{
|
||||||
Id = 1,
|
|
||||||
Format = _customFormatTwo,
|
Format = _customFormatTwo,
|
||||||
Score = 100
|
Score = 100
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||||
{
|
{
|
||||||
Mocker.SetConstant<IQualityProfileFormatItemsCleanupRepository>(
|
Mocker.SetConstant<IQualityProfileFormatItemsCleanupRepository>(
|
||||||
new QualityProfileFormatItemsCleanupRepository(Mocker.Resolve<IMainDatabase>(), Mocker.Resolve<IEventAggregator>()));
|
new QualityProfileFormatItemsCleanupRepository(Mocker.Resolve<IMainDatabase>(), Mocker.Resolve<IEventAggregator>()));
|
||||||
|
|
||||||
|
Mocker.SetConstant<ICustomFormatRepository>(
|
||||||
|
new CustomFormatRepository(Mocker.Resolve<IMainDatabase>(), Mocker.Resolve<IEventAggregator>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -30,7 +33,12 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||||
.With(h => h.Items = Qualities.QualityFixture.GetDefaultQualities())
|
.With(h => h.Items = Qualities.QualityFixture.GetDefaultQualities())
|
||||||
.With(h => h.MinFormatScore = 50)
|
.With(h => h.MinFormatScore = 50)
|
||||||
.With(h => h.CutoffFormatScore = 100)
|
.With(h => h.CutoffFormatScore = 100)
|
||||||
.With(h => h.FormatItems = Builder<ProfileFormatItem>.CreateListOfSize(1).Build().ToList())
|
.With(h => h.FormatItems = new List<ProfileFormatItem>
|
||||||
|
{
|
||||||
|
Builder<ProfileFormatItem>.CreateNew()
|
||||||
|
.With(c => c.Format = new CustomFormat("My Custom Format") { Id = 0 })
|
||||||
|
.Build()
|
||||||
|
})
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(qualityProfile);
|
Db.Insert(qualityProfile);
|
||||||
|
@ -62,9 +70,10 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||||
.With(h => h.CutoffFormatScore = cutoffFormatScore)
|
.With(h => h.CutoffFormatScore = cutoffFormatScore)
|
||||||
.With(h => h.FormatItems = new List<ProfileFormatItem>
|
.With(h => h.FormatItems = new List<ProfileFormatItem>
|
||||||
{
|
{
|
||||||
Builder<ProfileFormatItem>.CreateNew().With(f => f.Id = customFormat.Id).Build()
|
Builder<ProfileFormatItem>.CreateNew()
|
||||||
|
.With(c => c.Format = customFormat)
|
||||||
|
.Build()
|
||||||
})
|
})
|
||||||
|
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(qualityProfile);
|
Db.Insert(qualityProfile);
|
||||||
|
@ -77,5 +86,49 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||||
result.First().MinFormatScore.Should().Be(minFormatScore);
|
result.First().MinFormatScore.Should().Be(minFormatScore);
|
||||||
result.First().CutoffFormatScore.Should().Be(cutoffFormatScore);
|
result.First().CutoffFormatScore.Should().Be(cutoffFormatScore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_add_missing_custom_formats()
|
||||||
|
{
|
||||||
|
var minFormatScore = 50;
|
||||||
|
var cutoffFormatScore = 100;
|
||||||
|
|
||||||
|
var customFormat1 = Builder<CustomFormat>.CreateNew()
|
||||||
|
.With(h => h.Id = 1)
|
||||||
|
.With(h => h.Name = "Custom Format 1")
|
||||||
|
.With(h => h.Specifications = new List<ICustomFormatSpecification>())
|
||||||
|
.BuildNew();
|
||||||
|
|
||||||
|
var customFormat2 = Builder<CustomFormat>.CreateNew()
|
||||||
|
.With(h => h.Id = 2)
|
||||||
|
.With(h => h.Name = "Custom Format 2")
|
||||||
|
.With(h => h.Specifications = new List<ICustomFormatSpecification>())
|
||||||
|
.BuildNew();
|
||||||
|
|
||||||
|
Db.Insert(customFormat1);
|
||||||
|
Db.Insert(customFormat2);
|
||||||
|
|
||||||
|
var qualityProfile = Builder<QualityProfile>.CreateNew()
|
||||||
|
.With(h => h.Items = Qualities.QualityFixture.GetDefaultQualities())
|
||||||
|
.With(h => h.MinFormatScore = minFormatScore)
|
||||||
|
.With(h => h.CutoffFormatScore = cutoffFormatScore)
|
||||||
|
.With(h => h.FormatItems = new List<ProfileFormatItem>
|
||||||
|
{
|
||||||
|
Builder<ProfileFormatItem>.CreateNew()
|
||||||
|
.With(c => c.Format = customFormat1)
|
||||||
|
.Build()
|
||||||
|
})
|
||||||
|
.BuildNew();
|
||||||
|
|
||||||
|
Db.Insert(qualityProfile);
|
||||||
|
|
||||||
|
Subject.Clean();
|
||||||
|
var result = AllStoredModels;
|
||||||
|
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
result.First().FormatItems.Should().HaveCount(2);
|
||||||
|
result.First().MinFormatScore.Should().Be(minFormatScore);
|
||||||
|
result.First().CutoffFormatScore.Should().Be(cutoffFormatScore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,64 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dapper;
|
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.CustomFormats;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Profiles;
|
||||||
using NzbDrone.Core.Profiles.Qualities;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||||
{
|
{
|
||||||
public class CleanupQualityProfileFormatItems : IHousekeepingTask
|
public class CleanupQualityProfileFormatItems : IHousekeepingTask
|
||||||
{
|
{
|
||||||
private readonly IMainDatabase _database;
|
|
||||||
private readonly IQualityProfileFormatItemsCleanupRepository _repository;
|
private readonly IQualityProfileFormatItemsCleanupRepository _repository;
|
||||||
|
private readonly ICustomFormatRepository _customFormatRepository;
|
||||||
|
|
||||||
public CleanupQualityProfileFormatItems(IMainDatabase database, IQualityProfileFormatItemsCleanupRepository repository)
|
public CleanupQualityProfileFormatItems(IQualityProfileFormatItemsCleanupRepository repository,
|
||||||
|
ICustomFormatRepository customFormatRepository)
|
||||||
{
|
{
|
||||||
_database = database;
|
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
|
_customFormatRepository = customFormatRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clean()
|
public void Clean()
|
||||||
{
|
{
|
||||||
var customFormatIds = GetCustomFormatIds();
|
var test = _customFormatRepository.All();
|
||||||
|
var customFormats = _customFormatRepository.All().ToDictionary(c => c.Id);
|
||||||
var profiles = _repository.All();
|
var profiles = _repository.All();
|
||||||
var updatedProfiles = new List<QualityProfile>();
|
var updatedProfiles = new List<QualityProfile>();
|
||||||
|
|
||||||
foreach (var profile in profiles)
|
foreach (var profile in profiles)
|
||||||
{
|
{
|
||||||
var formatItems = profile.FormatItems.Where(f => customFormatIds.Contains(f.Id)).ToList();
|
var formatItems = new List<ProfileFormatItem>();
|
||||||
|
|
||||||
if (formatItems.Count != profile.FormatItems.Count)
|
// Make sure the profile doesn't include formats that have been removed
|
||||||
|
profile.FormatItems.ForEach(p =>
|
||||||
|
{
|
||||||
|
if (p.Format != null && customFormats.ContainsKey(p.Format.Id))
|
||||||
|
{
|
||||||
|
formatItems.Add(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure the profile includes all available formats
|
||||||
|
foreach (var customFormat in customFormats)
|
||||||
|
{
|
||||||
|
if (formatItems.None(f => f.Format.Id == customFormat.Key))
|
||||||
|
{
|
||||||
|
formatItems.Insert(0, new ProfileFormatItem
|
||||||
|
{
|
||||||
|
Format = customFormat.Value,
|
||||||
|
Score = 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousIds = profile.FormatItems.Select(i => i.Format.Id).ToList();
|
||||||
|
var ids = formatItems.Select(i => i.Format.Id).ToList();
|
||||||
|
|
||||||
|
// Update the profile if any formats were added or removed
|
||||||
|
if (ids.Except(previousIds).Any() || previousIds.Except(ids).Any())
|
||||||
{
|
{
|
||||||
profile.FormatItems = formatItems;
|
profile.FormatItems = formatItems;
|
||||||
|
|
||||||
|
@ -48,14 +77,6 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||||
_repository.SetFields(updatedProfiles, p => p.FormatItems, p => p.MinFormatScore, p => p.CutoffFormatScore);
|
_repository.SetFields(updatedProfiles, p => p.FormatItems, p => p.MinFormatScore, p => p.CutoffFormatScore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashSet<int> GetCustomFormatIds()
|
|
||||||
{
|
|
||||||
using (var mapper = _database.OpenConnection())
|
|
||||||
{
|
|
||||||
return new HashSet<int>(mapper.Query<int>("SELECT Id FROM CustomFormats"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IQualityProfileFormatItemsCleanupRepository : IBasicRepository<QualityProfile>
|
public interface IQualityProfileFormatItemsCleanupRepository : IBasicRepository<QualityProfile>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using NzbDrone.Core.CustomFormats;
|
using NzbDrone.Core.CustomFormats;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
@ -6,8 +5,6 @@ namespace NzbDrone.Core.Profiles
|
||||||
{
|
{
|
||||||
public class ProfileFormatItem : IEmbeddedDocument
|
public class ProfileFormatItem : IEmbeddedDocument
|
||||||
{
|
{
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
|
|
||||||
public int Id { get; set; }
|
|
||||||
public CustomFormat Format { get; set; }
|
public CustomFormat Format { get; set; }
|
||||||
public int Score { get; set; }
|
public int Score { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,6 @@ namespace NzbDrone.Core.Profiles.Qualities
|
||||||
|
|
||||||
var formatItems = _formatService.All().Select(format => new ProfileFormatItem
|
var formatItems = _formatService.All().Select(format => new ProfileFormatItem
|
||||||
{
|
{
|
||||||
Id = format.Id,
|
|
||||||
Score = 0,
|
Score = 0,
|
||||||
Format = format
|
Format = format
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
Loading…
Reference in New Issue