Added two optimisations to avoid duplicate work

Avoids many retrievals of ShellStateRecord and stops enabling the same
feature multiple times. This can significantly improve recipe execution
time for those recipes with large numbers of features with long
dependency chains.
This commit is contained in:
PaulDevenney
2015-11-25 17:41:03 +00:00
parent ab12ff6a05
commit 351e558fcd
2 changed files with 23 additions and 4 deletions

View File

@@ -1,4 +1,5 @@
using System.Linq; using System.Linq;
using Orchard.Caching;
using Orchard.Core.Settings.State.Records; using Orchard.Core.Settings.State.Records;
using Orchard.Data; using Orchard.Data;
using Orchard.Environment.State; using Orchard.Environment.State;
@@ -10,16 +11,19 @@ namespace Orchard.Core.Settings.State {
public class ShellStateManager : Component, IShellStateManager { public class ShellStateManager : Component, IShellStateManager {
private readonly IRepository<ShellStateRecord> _shellStateRepository; private readonly IRepository<ShellStateRecord> _shellStateRepository;
private readonly IShellDescriptorManager _shellDescriptorManager; private readonly IShellDescriptorManager _shellDescriptorManager;
private readonly ICacheManager _cacheManager;
public ShellStateManager( public ShellStateManager(
IRepository<ShellStateRecord> shellStateRepository, IRepository<ShellStateRecord> shellStateRepository,
IShellDescriptorManager shellDescriptorManager) { IShellDescriptorManager shellDescriptorManager,
ICacheManager cacheManager) {
_shellStateRepository = shellStateRepository; _shellStateRepository = shellStateRepository;
_shellDescriptorManager = shellDescriptorManager; _shellDescriptorManager = shellDescriptorManager;
_cacheManager = cacheManager;
} }
public ShellState GetShellState() { public ShellState GetShellState() {
var stateRecord = _shellStateRepository.Get(x => x != null) ?? new ShellStateRecord(); var stateRecord = GetExistingOrNewShellStateRecord();
var descriptor = _shellDescriptorManager.GetShellDescriptor(); var descriptor = _shellDescriptorManager.GetShellDescriptor();
var extraFeatures = descriptor == null ? Enumerable.Empty<string>() : descriptor.Features var extraFeatures = descriptor == null ? Enumerable.Empty<string>() : descriptor.Features
.Select(r => r.Name) .Select(r => r.Name)
@@ -38,9 +42,23 @@ namespace Orchard.Core.Settings.State {
.ToArray(), .ToArray(),
}; };
} }
private ShellStateRecord GetExistingOrNewShellStateRecord() {
//Fix for https://orchard.codeplex.com/workitem/21176 / https://github.com/OrchardCMS/Orchard/issues/6075 change to get ensure ShellState record only retrieved once.
var shellStateRecordId = _cacheManager.Get("ShellStateRecordId", ctx => {
var shellState = _shellStateRepository.Table.FirstOrDefault();
if (shellState == null) {
shellState = new ShellStateRecord();
_shellStateRepository.Create(shellState);
}
return shellState.Id;
});
return _shellStateRepository.Get(shellStateRecordId);
}
private ShellFeatureStateRecord FeatureRecord(string name) { private ShellFeatureStateRecord FeatureRecord(string name) {
var stateRecord = _shellStateRepository.Get(x => x != null) ?? new ShellStateRecord(); var stateRecord = GetExistingOrNewShellStateRecord();
var record = stateRecord.Features.SingleOrDefault(x => x.Name == name); var record = stateRecord.Features.SingleOrDefault(x => x.Name == name);
if (record == null) { if (record == null) {
record = new ShellFeatureStateRecord { Name = name }; record = new ShellFeatureStateRecord { Name = name };

View File

@@ -69,9 +69,10 @@ namespace Orchard.Environment.Features {
.ToDictionary(featureDescriptor => featureDescriptor, .ToDictionary(featureDescriptor => featureDescriptor,
featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name == featureDescriptor.Id) != null); featureDescriptor => enabledFeatures.FirstOrDefault(shellFeature => shellFeature.Name == featureDescriptor.Id) != null);
//Fix for https://orchard.codeplex.com/workitem/21176 / https://github.com/OrchardCMS/Orchard/issues/6075 - added distinct to the end to ensure each feature is only listed once
IEnumerable<string> featuresToEnable = featureIds IEnumerable<string> featuresToEnable = featureIds
.Select(featureId => EnableFeature(featureId, availableFeatures, force)).ToList() .Select(featureId => EnableFeature(featureId, availableFeatures, force)).ToList()
.SelectMany(ies => ies.Select(s => s)); .SelectMany(ies => ies.Select(s => s)).Distinct();
if (featuresToEnable.Count() > 0) { if (featuresToEnable.Count() > 0) {
foreach (string featureId in featuresToEnable) { foreach (string featureId in featuresToEnable) {