Skip to content

Commit

Permalink
Remove ShellDescriptorManager dependency on YesSql.ISession (#12906)
Browse files Browse the repository at this point in the history
  • Loading branch information
TFleury authored Dec 15, 2022
1 parent cf4662a commit 53cfa4c
Showing 1 changed file with 48 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -25,7 +24,7 @@ public class ShellDescriptorManager : IShellDescriptorManager
private readonly IEnumerable<ShellFeature> _alwaysEnabledFeatures;
private readonly IEnumerable<IShellDescriptorManagerEventHandler> _shellDescriptorManagerEventHandlers;
private readonly IExtensionManager _extensionManager;
private readonly ISession _session;
private readonly IDocumentStore _documentStore;
private readonly ILogger _logger;

private ShellDescriptor _shellDescriptor;
Expand All @@ -36,59 +35,70 @@ public ShellDescriptorManager(
IEnumerable<ShellFeature> shellFeatures,
IEnumerable<IShellDescriptorManagerEventHandler> shellDescriptorManagerEventHandlers,
IExtensionManager extensionManager,
ISession session,
IDocumentStore documentStore,
ILogger<ShellDescriptorManager> logger)
{
_shellSettings = shellSettings;
_shellConfiguration = shellConfiguration;
_alwaysEnabledFeatures = shellFeatures.Where(f => f.AlwaysEnabled).ToArray();
_shellDescriptorManagerEventHandlers = shellDescriptorManagerEventHandlers;
_extensionManager = extensionManager;
_session = session;
_documentStore = documentStore;
_logger = logger;
}

public async Task<ShellDescriptor> GetShellDescriptorAsync()
{
// Prevent multiple queries during the same request
if (_shellDescriptor == null)
if (_shellDescriptor != null)
{
_shellDescriptor = await _session.Query<ShellDescriptor>().FirstOrDefaultAsync();
return _shellDescriptor;
}

(var cacheable, var shellDescriptor) = await _documentStore.GetOrCreateImmutableAsync<ShellDescriptor>();

if (shellDescriptor.SerialNumber == 0)
{
return null;
}

if (_shellDescriptor != null)
if (!cacheable)
{
// Clone ShellDescriptor
shellDescriptor = new ShellDescriptor
{
var configuredFeatures = new ConfiguredFeatures();
_shellConfiguration.Bind(configuredFeatures);
SerialNumber = shellDescriptor.SerialNumber,
Installed = new List<ShellFeature>(shellDescriptor.Installed),
};
}

var features = _alwaysEnabledFeatures
.Concat(configuredFeatures.Features.Select(id => new ShellFeature(id) { AlwaysEnabled = true }))
.Concat(_shellDescriptor.Features)
.Distinct();
// Init shell descriptor and load features
var configuredFeatures = new ConfiguredFeatures();
_shellConfiguration.Bind(configuredFeatures);

var featureIds = features.Select(sf => sf.Id).ToArray();
var features = _alwaysEnabledFeatures
.Concat(configuredFeatures.Features.Select(id => new ShellFeature(id) { AlwaysEnabled = true }))
.Concat(shellDescriptor.Features)
.Distinct();

var missingDependencies = (await _extensionManager.LoadFeaturesAsync(featureIds))
.Select(entry => entry.FeatureInfo.Id)
.Except(featureIds)
.Select(id => new ShellFeature(id));
var featureIds = features.Select(sf => sf.Id).ToArray();

_shellDescriptor.Features = features
.Concat(missingDependencies)
.ToList();
}
}
var missingDependencies = (await _extensionManager.LoadFeaturesAsync(featureIds))
.Select(entry => entry.FeatureInfo.Id)
.Except(featureIds)
.Select(id => new ShellFeature(id));

return _shellDescriptor;
shellDescriptor.Features = features
.Concat(missingDependencies)
.ToList();

return _shellDescriptor = shellDescriptor;
}

public async Task UpdateShellDescriptorAsync(int priorSerialNumber, IEnumerable<ShellFeature> enabledFeatures)
{
var shellDescriptorRecord = await GetShellDescriptorAsync();
var serialNumber = shellDescriptorRecord == null
? 0
: shellDescriptorRecord.SerialNumber;
var shellDescriptor = await _documentStore.GetOrCreateMutableAsync<ShellDescriptor>();

if (priorSerialNumber != serialNumber)
if (priorSerialNumber != shellDescriptor.SerialNumber)
{
throw new InvalidOperationException("Invalid serial number for shell descriptor");
}
Expand All @@ -98,32 +108,22 @@ 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);
await _documentStore.CommitAsync();

// 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 _shellDescriptorManagerEventHandlers.InvokeAsync((handler, shellDescriptorRecord, _shellSettings) =>
handler.ChangedAsync(shellDescriptorRecord, _shellSettings), shellDescriptorRecord, _shellSettings, _logger);
await _shellDescriptorManagerEventHandlers.InvokeAsync((handler, shellDescriptor, _shellSettings) =>
handler.ChangedAsync(shellDescriptor, _shellSettings), shellDescriptor, _shellSettings, _logger);
}

private class ConfiguredFeatures
Expand Down

0 comments on commit 53cfa4c

Please sign in to comment.