From 9392718d3e63c056fcea0a59883b288f6491bb30 Mon Sep 17 00:00:00 2001 From: Matteo Piovanelli Date: Thu, 7 May 2020 19:35:53 +0200 Subject: [PATCH] Cache list of configured layers (#8373) On every page load on frontend we were querying for all existing layers to test for the ones that are currently active. Since that information is not bound to change often, we added a cache layer to prevent querying every time. The cache is evicted whenever a Layer gets updated. --- .../Handlers/LayerPartHandler.cs | 26 +++++++++++++++++-- .../Orchard.Widgets/Models/LayerPart.cs | 5 ++++ .../Services/DefaultLayerEvaluationService.cs | 22 ++++++++++++++-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Handlers/LayerPartHandler.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Handlers/LayerPartHandler.cs index 89d929582..22f6e12d0 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Handlers/LayerPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Handlers/LayerPartHandler.cs @@ -1,12 +1,30 @@ -using Orchard.ContentManagement; +using Orchard.Caching; +using Orchard.ContentManagement; using Orchard.ContentManagement.Handlers; using Orchard.Data; using Orchard.Widgets.Models; namespace Orchard.Widgets.Handlers { public class LayerPartHandler : ContentHandler { - public LayerPartHandler(IRepository layersRepository) { + private readonly ISignals _signals; + public LayerPartHandler( + IRepository layersRepository, + ISignals signals) { + Filters.Add(StorageFilter.For(layersRepository)); + _signals = signals; + + // Evict cached content when updated, removed or destroyed. + OnUpdated( + (context, part) => Invalidate()); + OnImported( + (context, part) => Invalidate()); + OnPublished( + (context, part) => Invalidate()); + OnRemoved( + (context, part) => Invalidate()); + OnDestroyed( + (context, part) => Invalidate()); } protected override void GetItemMetadata(GetContentItemMetadataContext context) { @@ -16,5 +34,9 @@ namespace Orchard.Widgets.Handlers { context.Metadata.Identity.Add("Layer.LayerName", part.Name); } } + + private void Invalidate() { + _signals.Trigger(LayerPart.AllLayersCacheEvictSignal); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs index 02f728819..2ee3ede03 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs @@ -29,5 +29,10 @@ namespace Orchard.Widgets.Models { get { return Retrieve(x => x.LayerRule); } set { Store(x => x.LayerRule, value); } } + + public static string AllLayersCacheEvictSignal = + "LayerPart_AllLayers_EvictCache"; + public static string AllLayersCacheKey = + "LayerPart_AllLayers_CacheKey"; } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Services/DefaultLayerEvaluationService.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Services/DefaultLayerEvaluationService.cs index 4f9633deb..8cb36a26a 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Services/DefaultLayerEvaluationService.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Services/DefaultLayerEvaluationService.cs @@ -6,17 +6,27 @@ using Orchard.Logging; using Orchard.Widgets.Models; using Orchard.ContentManagement; using Orchard.ContentManagement.Utilities; +using Orchard.Caching; namespace Orchard.Widgets.Services{ public class DefaultLayerEvaluationService : ILayerEvaluationService { private readonly IConditionManager _conditionManager; private readonly IOrchardServices _orchardServices; + private readonly ICacheManager _cacheManager; + private readonly ISignals _signals; private readonly LazyField _activeLayerIDs; - public DefaultLayerEvaluationService(IConditionManager conditionManager, IOrchardServices orchardServices) { + public DefaultLayerEvaluationService( + IConditionManager conditionManager, + IOrchardServices orchardServices, + ICacheManager cacheManager, + ISignals signals) { + _conditionManager = conditionManager; _orchardServices = orchardServices; + _cacheManager = cacheManager; + _signals = signals; Logger = NullLogger.Instance; T = NullLocalizer.Instance; @@ -42,7 +52,15 @@ namespace Orchard.Widgets.Services{ // Once the Condition Engine is done: // Get Layers and filter by zone and rule // NOTE: .ForType("Layer") is faster than .Query() - var activeLayers = _orchardServices.ContentManager.Query().ForType("Layer").List(); + var activeLayers = _cacheManager.Get(LayerPart.AllLayersCacheKey, true, ctx => { + // invalidation signal + ctx.Monitor(_signals.When(LayerPart.AllLayersCacheEvictSignal)); + // cache + return _orchardServices + .ContentManager + .Query() + .ForType("Layer").List(); + }); var activeLayerIds = new List(); foreach (var activeLayer in activeLayers) {