Fix/8354 caching (#8364)

* Caching the ShellDescriptor
This avoids fetching all connected records on every request.
refreshed cache after an update
This is after having evicted it and having updated the database
This commit is contained in:
Matteo Piovanelli
2020-05-08 08:31:33 +02:00
committed by GitHub
parent e520a178aa
commit d85ff5fa37

View File

@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Caching;
using Orchard.Core.Settings.Descriptor.Records;
using Orchard.Data;
using Orchard.Environment.Configuration;
using Orchard.Environment.Descriptor;
using Orchard.Environment.Descriptor.Models;
using Orchard.Locking;
using Orchard.Logging;
namespace Orchard.Core.Settings.Descriptor {
@@ -13,14 +15,28 @@ namespace Orchard.Core.Settings.Descriptor {
private readonly IRepository<ShellDescriptorRecord> _shellDescriptorRepository;
private readonly IShellDescriptorManagerEventHandler _events;
private readonly ShellSettings _shellSettings;
private readonly ILockingProvider _lockingProvider;
private readonly ICacheManager _cacheManager;
private readonly ISignals _signals;
public ShellDescriptorManager(
IRepository<ShellDescriptorRecord> shellDescriptorRepository,
IShellDescriptorManagerEventHandler events,
ShellSettings shellSettings) {
ShellSettings shellSettings,
ILockingProvider lockingProvider,
ICacheManager cacheManager,
ISignals signals) {
_shellDescriptorRepository = shellDescriptorRepository;
_events = events;
_shellSettings = shellSettings;
_lockingProvider = lockingProvider;
_cacheManager = cacheManager;
_signals = signals;
_lockString = string.Join(".",
_shellSettings["Name"] ?? "",
"ShellDescriptorManager");
}
public ShellDescriptor GetShellDescriptor() {
@@ -50,47 +66,72 @@ namespace Orchard.Core.Settings.Descriptor {
return descriptor;
}
private const string EvictSignalName =
"ShellDescriptorRecord_EvictCache";
private const string DescriptorCacheName =
"Orchard.Core.Settings.Descriptor.ShellDescriptorManager.ShellDescriptorRecord";
private ShellDescriptorRecord GetDescriptorRecord() {
return _shellDescriptorRepository.Get(x => x != null);
// fetching the ShellDescriptorRecord also causes NHibernate to launch
// SELECT queries to fetch the ShellFeatureRecords and the ShellParameterRecords.
// If we cache all that, we save those three select queries on every request.
// We should be careful in the eviction policy when the ShellDescriptorRecord
// gets updated.
return _cacheManager.Get(DescriptorCacheName, true, ctx => {
ctx.Monitor(_signals.When(EvictSignalName));
return _shellDescriptorRepository.Get(x => x != null);
});
}
public void UpdateShellDescriptor(int priorSerialNumber, IEnumerable<ShellFeature> enabledFeatures, IEnumerable<ShellParameter> parameters) {
ShellDescriptorRecord shellDescriptorRecord = GetDescriptorRecord();
var serialNumber = shellDescriptorRecord == null ? 0 : shellDescriptorRecord.SerialNumber;
if (priorSerialNumber != serialNumber)
throw new InvalidOperationException(T("Invalid serial number for shell descriptor").ToString());
private string _lockString;
Logger.Information("Updating shell descriptor for shell '{0}'...", _shellSettings.Name);
public void UpdateShellDescriptor(
int priorSerialNumber, IEnumerable<ShellFeature> enabledFeatures, IEnumerable<ShellParameter> parameters) {
// This is where the shell descriptor will be updated.
// Since we plan to cache it, this method will have to update the
// actual records in the database, and then evict the cache.
// We are going to put an application lock around this to prevent
// issues when for some weird reason several updates are being attempted
// concurrently.
_lockingProvider.Lock(_lockString, () => {
ShellDescriptorRecord shellDescriptorRecord = _shellDescriptorRepository.Get(x => x != null);
var serialNumber = shellDescriptorRecord == null ? 0 : shellDescriptorRecord.SerialNumber;
if (priorSerialNumber != serialNumber)
throw new InvalidOperationException(T("Invalid serial number for shell descriptor").ToString());
if (shellDescriptorRecord == null) {
shellDescriptorRecord = new ShellDescriptorRecord { SerialNumber = 1 };
_shellDescriptorRepository.Create(shellDescriptorRecord);
}
else {
shellDescriptorRecord.SerialNumber++;
}
Logger.Information("Updating shell descriptor for shell '{0}'...", _shellSettings.Name);
shellDescriptorRecord.Features.Clear();
foreach (var feature in enabledFeatures) {
shellDescriptorRecord.Features.Add(new ShellFeatureRecord { Name = feature.Name, ShellDescriptorRecord = shellDescriptorRecord });
}
Logger.Debug("Enabled features for shell '{0}' set: {1}.", _shellSettings.Name, String.Join(", ", enabledFeatures.Select(feature => feature.Name)));
if (shellDescriptorRecord == null) {
shellDescriptorRecord = new ShellDescriptorRecord { SerialNumber = 1 };
_shellDescriptorRepository.Create(shellDescriptorRecord);
} else {
shellDescriptorRecord.SerialNumber++;
}
shellDescriptorRecord.Features.Clear();
foreach (var feature in enabledFeatures) {
shellDescriptorRecord.Features.Add(new ShellFeatureRecord { Name = feature.Name, ShellDescriptorRecord = shellDescriptorRecord });
}
Logger.Debug("Enabled features for shell '{0}' set: {1}.", _shellSettings.Name, String.Join(", ", enabledFeatures.Select(feature => feature.Name)));
shellDescriptorRecord.Parameters.Clear();
foreach (var parameter in parameters) {
shellDescriptorRecord.Parameters.Add(new ShellParameterRecord {
Component = parameter.Component,
Name = parameter.Name,
Value = parameter.Value,
ShellDescriptorRecord = shellDescriptorRecord
});
}
Logger.Debug("Parameters for shell '{0}' set: {1}.", _shellSettings.Name, String.Join(", ", parameters.Select(parameter => parameter.Name + "-" + parameter.Value)));
shellDescriptorRecord.Parameters.Clear();
foreach (var parameter in parameters) {
shellDescriptorRecord.Parameters.Add(new ShellParameterRecord {
Component = parameter.Component,
Name = parameter.Name,
Value = parameter.Value,
ShellDescriptorRecord = shellDescriptorRecord
});
}
Logger.Information("Shell descriptor updated for shell '{0}'.", _shellSettings.Name);
_signals.Trigger(EvictSignalName);
_events.Changed(GetShellDescriptorFromRecord(shellDescriptorRecord), _shellSettings.Name);
Logger.Debug("Parameters for shell '{0}' set: {1}.", _shellSettings.Name, String.Join(", ", parameters.Select(parameter => parameter.Name + "-" + parameter.Value)));
Logger.Information("Shell descriptor updated for shell '{0}'.", _shellSettings.Name);
_events.Changed(GetShellDescriptorFromRecord(GetDescriptorRecord()), _shellSettings.Name);
});
}
}
}