From 351e558fcd9bbfa4b4f627eec75648532168df74 Mon Sep 17 00:00:00 2001 From: PaulDevenney Date: Wed, 25 Nov 2015 17:41:03 +0000 Subject: [PATCH] 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. --- .../Core/Settings/State/ShellStateManager.cs | 24 ++++++++++++++++--- .../Environment/Features/FeatureManager.cs | 3 ++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Core/Settings/State/ShellStateManager.cs b/src/Orchard.Web/Core/Settings/State/ShellStateManager.cs index b1bd059ac..f0fc859d4 100644 --- a/src/Orchard.Web/Core/Settings/State/ShellStateManager.cs +++ b/src/Orchard.Web/Core/Settings/State/ShellStateManager.cs @@ -1,4 +1,5 @@ using System.Linq; +using Orchard.Caching; using Orchard.Core.Settings.State.Records; using Orchard.Data; using Orchard.Environment.State; @@ -10,16 +11,19 @@ namespace Orchard.Core.Settings.State { public class ShellStateManager : Component, IShellStateManager { private readonly IRepository _shellStateRepository; private readonly IShellDescriptorManager _shellDescriptorManager; + private readonly ICacheManager _cacheManager; public ShellStateManager( IRepository shellStateRepository, - IShellDescriptorManager shellDescriptorManager) { + IShellDescriptorManager shellDescriptorManager, + ICacheManager cacheManager) { _shellStateRepository = shellStateRepository; _shellDescriptorManager = shellDescriptorManager; + _cacheManager = cacheManager; } public ShellState GetShellState() { - var stateRecord = _shellStateRepository.Get(x => x != null) ?? new ShellStateRecord(); + var stateRecord = GetExistingOrNewShellStateRecord(); var descriptor = _shellDescriptorManager.GetShellDescriptor(); var extraFeatures = descriptor == null ? Enumerable.Empty() : descriptor.Features .Select(r => r.Name) @@ -38,9 +42,23 @@ namespace Orchard.Core.Settings.State { .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) { - var stateRecord = _shellStateRepository.Get(x => x != null) ?? new ShellStateRecord(); + var stateRecord = GetExistingOrNewShellStateRecord(); var record = stateRecord.Features.SingleOrDefault(x => x.Name == name); if (record == null) { record = new ShellFeatureStateRecord { Name = name }; diff --git a/src/Orchard/Environment/Features/FeatureManager.cs b/src/Orchard/Environment/Features/FeatureManager.cs index 8317e0f7b..6e5a9e34e 100644 --- a/src/Orchard/Environment/Features/FeatureManager.cs +++ b/src/Orchard/Environment/Features/FeatureManager.cs @@ -69,9 +69,10 @@ namespace Orchard.Environment.Features { .ToDictionary(featureDescriptor => featureDescriptor, 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 featuresToEnable = featureIds .Select(featureId => EnableFeature(featureId, availableFeatures, force)).ToList() - .SelectMany(ies => ies.Select(s => s)); + .SelectMany(ies => ies.Select(s => s)).Distinct(); if (featuresToEnable.Count() > 0) { foreach (string featureId in featuresToEnable) {