From a4dc1943b976e147f37f4b322495bfb4f5b0d765 Mon Sep 17 00:00:00 2001 From: Thierry Fleury Date: Sat, 3 Dec 2022 13:31:20 +0100 Subject: [PATCH] Fixes #10311 : Remove ShellDescriptorManager dependency on YesSql.ISession --- .../Shell/ShellDescriptorManager.cs | 86 +++++++++---------- 1 file changed, 39 insertions(+), 47 deletions(-) diff --git a/src/OrchardCore/OrchardCore.Infrastructure/Shell/ShellDescriptorManager.cs b/src/OrchardCore/OrchardCore.Infrastructure/Shell/ShellDescriptorManager.cs index a1f33d7ecbb..6377741789f 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure/Shell/ShellDescriptorManager.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure/Shell/ShellDescriptorManager.cs @@ -2,16 +2,15 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Dapper; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using OrchardCore.Data.Documents; using OrchardCore.Environment.Extensions; using OrchardCore.Environment.Shell.Configuration; using OrchardCore.Environment.Shell.Descriptor; using OrchardCore.Environment.Shell.Descriptor.Models; using OrchardCore.Modules; -using YesSql; namespace OrchardCore.Environment.Shell.Data.Descriptors { @@ -25,18 +24,16 @@ public class ShellDescriptorManager : IShellDescriptorManager private readonly IEnumerable _alwaysEnabledFeatures; private readonly IEnumerable _shellDescriptorManagerEventHandlers; private readonly IExtensionManager _extensionManager; - private readonly ISession _session; + private readonly IDocumentStore _documentStore; private readonly ILogger _logger; - private ShellDescriptor _shellDescriptor; - public ShellDescriptorManager( ShellSettings shellSettings, IShellConfiguration shellConfiguration, IEnumerable shellFeatures, IEnumerable shellDescriptorManagerEventHandlers, IExtensionManager extensionManager, - ISession session, + IDocumentStore documentStore, ILogger logger) { _shellSettings = shellSettings; @@ -44,51 +41,49 @@ public ShellDescriptorManager( _alwaysEnabledFeatures = shellFeatures.Where(f => f.AlwaysEnabled).ToArray(); _shellDescriptorManagerEventHandlers = shellDescriptorManagerEventHandlers; _extensionManager = extensionManager; - _session = session; + _documentStore = documentStore; _logger = logger; } public async Task GetShellDescriptorAsync() { - // Prevent multiple queries during the same request - if (_shellDescriptor == null) + (bool cacheable, ShellDescriptor shellDescriptor) = await _documentStore.GetOrCreateImmutableAsync(ShellDescriptorFactory); + + if (shellDescriptor.SerialNumber== 0) { - _shellDescriptor = await _session.Query().FirstOrDefaultAsync(); + return null; + } - if (_shellDescriptor != null) - { - var configuredFeatures = new ConfiguredFeatures(); - _shellConfiguration.Bind(configuredFeatures); + if (cacheable) { + // Init shell descriptor and load features + var configuredFeatures = new ConfiguredFeatures(); + _shellConfiguration.Bind(configuredFeatures); - var features = _alwaysEnabledFeatures - .Concat(configuredFeatures.Features.Select(id => new ShellFeature(id) { AlwaysEnabled = true })) - .Concat(_shellDescriptor.Features) - .Distinct(); + var features = _alwaysEnabledFeatures + .Concat(configuredFeatures.Features.Select(id => new ShellFeature(id) { AlwaysEnabled = true })) + .Concat(shellDescriptor.Features) + .Distinct(); - var featureIds = features.Select(sf => sf.Id).ToArray(); + var featureIds = features.Select(sf => sf.Id).ToArray(); - var missingDependencies = (await _extensionManager.LoadFeaturesAsync(featureIds)) - .Select(entry => entry.FeatureInfo.Id) - .Except(featureIds) - .Select(id => new ShellFeature(id)); + var missingDependencies = (await _extensionManager.LoadFeaturesAsync(featureIds)) + .Select(entry => entry.FeatureInfo.Id) + .Except(featureIds) + .Select(id => new ShellFeature(id)); - _shellDescriptor.Features = features - .Concat(missingDependencies) - .ToList(); - } + shellDescriptor.Features = features + .Concat(missingDependencies) + .ToList(); } - return _shellDescriptor; + return shellDescriptor; } public async Task UpdateShellDescriptorAsync(int priorSerialNumber, IEnumerable enabledFeatures) { - var shellDescriptorRecord = await GetShellDescriptorAsync(); - var serialNumber = shellDescriptorRecord == null - ? 0 - : shellDescriptorRecord.SerialNumber; + var shellDescriptor = await _documentStore.GetOrCreateMutableAsync(ShellDescriptorFactory); - if (priorSerialNumber != serialNumber) + if (priorSerialNumber != shellDescriptor.SerialNumber) { throw new InvalidOperationException("Invalid serial number for shell descriptor"); } @@ -98,32 +93,29 @@ public async Task UpdateShellDescriptorAsync(int priorSerialNumber, IEnumerable< _logger.LogInformation("Updating shell descriptor for tenant '{TenantName}' ...", _shellSettings.Name); } - if (shellDescriptorRecord == null) - { - shellDescriptorRecord = new ShellDescriptor { SerialNumber = 1 }; - } - else - { - shellDescriptorRecord.SerialNumber++; - } - - shellDescriptorRecord.Features = _alwaysEnabledFeatures.Union(enabledFeatures).ToList(); - shellDescriptorRecord.Installed = shellDescriptorRecord.Installed.Union(shellDescriptorRecord.Features).ToList(); + shellDescriptor.SerialNumber++; + shellDescriptor.Features = _alwaysEnabledFeatures.Union(enabledFeatures).ToList(); + shellDescriptor.Installed = shellDescriptor.Installed.Union(shellDescriptor.Features).ToList(); if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Shell descriptor updated for tenant '{TenantName}'.", _shellSettings.Name); } - _session.Save(shellDescriptorRecord); + await _documentStore.UpdateAsync(shellDescriptor, (_) => Task.CompletedTask); // In the 'ChangedAsync()' event the shell will be released so that, on request, a new one will be built. // So, we commit the session earlier to prevent a new shell from being built from an outdated descriptor. - await _session.SaveChangesAsync(); + await _documentStore.CommitAsync(); await _shellDescriptorManagerEventHandlers.InvokeAsync((handler, shellDescriptorRecord, _shellSettings) => - handler.ChangedAsync(shellDescriptorRecord, _shellSettings), shellDescriptorRecord, _shellSettings, _logger); + handler.ChangedAsync(shellDescriptorRecord, _shellSettings), shellDescriptor, _shellSettings, _logger); + } + + private static Task ShellDescriptorFactory() + { + return Task.FromResult(new ShellDescriptor { SerialNumber = 0 }); } private class ConfiguredFeatures