From 9d406dda372e26900dcf77574bdb47b395c40fb9 Mon Sep 17 00:00:00 2001 From: jtkech Date: Mon, 9 Oct 2023 08:29:42 +0200 Subject: [PATCH] Check DistributedShellMarkerService --- .../Shell/Distributed/DistributedContext.cs | 2 - .../DistributedShellHostedService.cs | 128 +++++++++--------- 2 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedContext.cs b/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedContext.cs index 9e3a9b37fb3..032352e33c7 100644 --- a/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedContext.cs +++ b/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedContext.cs @@ -38,8 +38,6 @@ public DistributedContext(ShellContext context) public IDistributedCache DistributedCache { get; } - public bool HasIsolatedConfiguration { get; internal set; } - public DistributedContext Acquire() { // Don't acquire a released context. diff --git a/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedShellHostedService.cs b/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedShellHostedService.cs index 406222f4fde..122976a8f37 100644 --- a/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedShellHostedService.cs +++ b/src/OrchardCore/OrchardCore/Shell/Distributed/DistributedShellHostedService.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using OrchardCore.Environment.Shell.Builders; @@ -43,7 +44,7 @@ internal class DistributedShellHostedService : BackgroundService private DistributedContext _context; private DateTime _busyStartTime; - private bool _terminated; + private bool _initialized; public DistributedShellHostedService( IShellHost shellHost, @@ -58,7 +59,6 @@ public DistributedShellHostedService( _shellRemovingManager = shellRemovingManager; _logger = logger; - shellHost.LoadingAsync += LoadingAsync; shellHost.ReleasingAsync += ReleasingAsync; shellHost.ReloadingAsync += ReloadingAsync; shellHost.RemovingAsync += RemovingAsync; @@ -139,6 +139,17 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) continue; } + // Initialize the service if not yet done by using the distributed cache. + try + { + await EnsureInitializedAsync(distributedCache); + } + catch (Exception ex) when (!ex.IsFatal()) + { + // Get the next idle time before retrying to use the distributed cache. + idleTime = NextIdleTimeBeforeRetry(idleTime, ex); + } + // Try to retrieve the tenant changed global identifier from the distributed cache. string shellChangedId; try @@ -307,7 +318,11 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } } - _terminated = true; + _initialized = false; + + _shellHost.ReleasingAsync -= ReleasingAsync; + _shellHost.ReloadingAsync -= ReloadingAsync; + _shellHost.RemovingAsync -= RemovingAsync; if (_context is not null) { @@ -318,41 +333,11 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } /// - /// Called before loading all tenants to initialize the local shell identifiers from the distributed cache. + /// Initialize the local shell identifiers from the distributed cache. /// - public async Task LoadingAsync() + public async Task EnsureInitializedAsync(IDistributedCache distributedCache) { - if (_terminated) - { - return; - } - - // Load a first isolated configuration as the default context it is not yet initialized. - var defaultSettings = (await _shellSettingsManager - .LoadSettingsAsync(ShellSettings.DefaultShellName)) - .AsDisposable(); - - // If there is no default tenant or it is not running, nothing to do. - if (!defaultSettings.IsRunning()) - { - defaultSettings.Dispose(); - return; - } - - // Create a distributed context based on the first isolated configuration. - var context = _context = await CreateDistributedContextAsync(defaultSettings); - if (context is null) - { - defaultSettings.Dispose(); - return; - } - - // Mark the context as using the first isolated configuration. - context.HasIsolatedConfiguration = true; - - // If the required distributed features are not enabled, nothing to do. - var distributedCache = context.DistributedCache; - if (distributedCache is null) + if (_initialized) { return; } @@ -389,10 +374,12 @@ public async Task LoadingAsync() // Keep in sync the tenant global identifiers. _shellChangedId = shellChangedId; _shellCountChangedId = shellCountChangedId; + + _initialized = true; } catch (Exception ex) when (!ex.IsFatal()) { - _logger.LogError(ex, "Unable to read the distributed cache before loading all tenants."); + _logger.LogError(ex, "Unable to read the distributed cache while initializing the tenant identifiers."); } } @@ -401,7 +388,7 @@ public async Task LoadingAsync() /// public async Task ReleasingAsync(string name) { - if (_terminated) + if (!_initialized) { return; } @@ -452,7 +439,7 @@ public async Task ReleasingAsync(string name) /// public async Task ReloadingAsync(string name) { - if (_terminated) + if (!_initialized) { return; } @@ -467,13 +454,6 @@ public async Task ReloadingAsync(string name) // Acquire the distributed context or create a new one if not yet built. await using var context = await AcquireOrCreateDistributedContextAsync(defaultContext); - // If the context still use the first isolated configuration. - if (context is not null && context.HasIsolatedConfiguration) - { - // Reset the serial number so that a new context will be built. - context.Context.Blueprint.Descriptor.SerialNumber = 0; - } - // If the required distributed features are not enabled, nothing to do. var distributedCache = context?.DistributedCache; if (distributedCache is null) @@ -518,7 +498,7 @@ public async Task ReloadingAsync(string name) public async Task RemovingAsync(string name) { // The 'Default' tenant can't be removed. - if (_terminated || name.IsDefaultShellName()) + if (!_initialized || name.IsDefaultShellName()) { return; } @@ -562,14 +542,21 @@ public async Task RemovingAsync(string name) } } - private static string ReleaseIdKey(string name) => name + ReleaseIdKeySuffix; - private static string ReloadIdKey(string name) => name + ReloadIdKeySuffix; + private static string ReleaseIdKey(string name) => $"{name}{ReleaseIdKeySuffix}"; + private static string ReloadIdKey(string name) => $"{name}{ReloadIdKeySuffix}"; /// /// Creates a distributed context based on the default tenant context. /// private async Task CreateDistributedContextAsync(ShellContext defaultContext) { + // Check if the distributed shell feature is enabled. + if (!HasDistributedShellFeature(defaultContext)) + { + // Nothing to create. + return null; + } + // Get the default tenant descriptor. var descriptor = await GetDefaultShellDescriptorAsync(defaultContext); @@ -601,21 +588,6 @@ private async Task CreateDistributedContextAsync(ShellSettin } } - /// - /// Creates a distributed context based on the default tenant settings. - /// - private async Task CreateDistributedContextAsync(ShellSettings defaultSettings) - { - try - { - return new DistributedContext(await _shellContextFactory.CreateShellContextAsync(defaultSettings)); - } - catch - { - return null; - } - } - /// /// Gets the default tenant descriptor. /// @@ -679,6 +651,13 @@ private async Task GetOrCreateDistributedContextAsync(ShellC /// private async Task ReuseOrCreateDistributedContextAsync(ShellContext defaultContext) { + // Check if the distributed shell feature is enabled. + if (!HasDistributedShellFeature(defaultContext)) + { + // Nothing to create. + return null; + } + // If no context. if (_context is null) { @@ -698,7 +677,7 @@ private async Task ReuseOrCreateDistributedContextAsync(Shel // If no descriptor. if (descriptor is null) - { + { // Nothing to create. return null; } @@ -731,6 +710,25 @@ private Task AcquireOrCreateDistributedContextAsync(ShellCon return Task.FromResult(distributedContext); } + /// + /// Whether the default context has the distributed shell feature enabled or not. + /// + private static bool HasDistributedShellFeature(ShellContext defaultContext) + { + try + { + if (defaultContext.ServiceProvider?.GetService() is not null) + { + return true; + } + } + catch + { + } + + return false; + } + /// /// Gets the next idle time before retrying to read the distributed cache. ///