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.
This commit is contained in:
Matteo Piovanelli
2020-05-07 19:35:53 +02:00
committed by GitHub
parent 60464035f7
commit 9392718d3e
3 changed files with 49 additions and 4 deletions

View File

@@ -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<LayerPartRecord> layersRepository) {
private readonly ISignals _signals;
public LayerPartHandler(
IRepository<LayerPartRecord> layersRepository,
ISignals signals) {
Filters.Add(StorageFilter.For(layersRepository));
_signals = signals;
// Evict cached content when updated, removed or destroyed.
OnUpdated<LayerPart>(
(context, part) => Invalidate());
OnImported<LayerPart>(
(context, part) => Invalidate());
OnPublished<LayerPart>(
(context, part) => Invalidate());
OnRemoved<LayerPart>(
(context, part) => Invalidate());
OnDestroyed<LayerPart>(
(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);
}
}
}

View File

@@ -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";
}
}

View File

@@ -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<int[]> _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<LayerPart, LayerPartRecord>()
var activeLayers = _orchardServices.ContentManager.Query<LayerPart>().ForType("Layer").List();
var activeLayers = _cacheManager.Get(LayerPart.AllLayersCacheKey, true, ctx => {
// invalidation signal
ctx.Monitor(_signals.When(LayerPart.AllLayersCacheEvictSignal));
// cache
return _orchardServices
.ContentManager
.Query<LayerPart>()
.ForType("Layer").List();
});
var activeLayerIds = new List<int>();
foreach (var activeLayer in activeLayers) {