diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Constants/IdleTenantData.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Constants/IdleTenantData.cs new file mode 100644 index 00000000..8716f37d --- /dev/null +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Constants/IdleTenantData.cs @@ -0,0 +1,8 @@ +namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI.Constants; + +public static class IdleTenantData +{ + public const string IdleTenantName = nameof(IdleTenantName); + public const string IdleTenantPrefix = "idletenantprefix"; + public const string IdleTenantRecipe = "Lombiq.OSOCE.Tests"; +} diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs index 7fcaf6d8..3eff499b 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs @@ -3,6 +3,7 @@ using Shouldly; using System; using System.Threading.Tasks; +using static Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI.Constants.IdleTenantData; namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI.Extensions; @@ -26,5 +27,5 @@ public static void SetMaxIdleMinutesAndLoggingForUITest( public static readonly Func AssertAppLogsWithIdleCheckAsync = async webApplicationInstance => (await webApplicationInstance.GetLogOutputAsync()) - .ShouldContain("Shutting down tenant \"Default\" because of idle timeout."); + .ShouldContain($"Shutting down tenant \"{IdleTenantName}\" because of idle timeout."); } diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs index 88604e50..ee18f1d5 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs @@ -1,13 +1,32 @@ using Lombiq.Tests.UI.Extensions; +using Lombiq.Tests.UI.Pages; using Lombiq.Tests.UI.Services; using System.Threading.Tasks; +using static Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI.Constants.IdleTenantData; namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI.Extensions; public static class TestCaseUITestContextExtensions { - public static async Task TestIdleTenantManagerBehaviorAsync(this UITestContext context) + public static async Task TestIdleTenantManagerBehaviorAsync( + this UITestContext context) { + // Setting up new tenant to test the feature + await context.CreateAndSwitchToTenantManuallyAsync(IdleTenantName, IdleTenantPrefix, string.Empty); + + // Because this test is aimed at a single tenant's behavior we don't need dynamic tenant data. + // The used constants here can be found at IdleTenantManagement.Tests.UI/Constants/IdleTenantData. + await context.GoToSetupPageAndSetupOrchardCoreAsync( + new OrchardCoreSetupParameters(context) + { + SiteName = IdleTenantName, + RecipeId = IdleTenantRecipe, + TablePrefix = IdleTenantName, + RunSetupOnCurrentPage = true, + }); + + await context.SignInDirectlyAsync(); + // We are letting the site to sit idle for more than two minutes so that the tenant could be shut down by the // background task. await Task.Delay(129420); diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs index 60e37ecc..64149ed4 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs @@ -16,54 +16,25 @@ public class IdleShutdownTask : IBackgroundTask { public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken) { - var clock = serviceProvider.GetService(); - var lastActiveTimeAccessor = serviceProvider.GetService(); - var shellHost = serviceProvider.GetService(); + var maxIdleMinutes = serviceProvider.GetRequiredService>().Value.MaxIdleMinutes; - var options = serviceProvider.GetService>(); - var maxIdleMinutes = options.Value.MaxIdleMinutes; + var shellSettings = serviceProvider.GetRequiredService(); - if (maxIdleMinutes <= 0) return; + if (maxIdleMinutes <= 0 || shellSettings.IsDefaultShell()) return; - if (lastActiveTimeAccessor.LastActiveDateTimeUtc.AddMinutes(maxIdleMinutes) <= clock?.UtcNow) - { - var shellSettings = serviceProvider.GetService(); - var logger = serviceProvider.GetService>(); + var clock = serviceProvider.GetRequiredService(); - logger?.LogInformation("Shutting down tenant \"{ShellName}\" because of idle timeout.", shellSettings?.Name); + var lastActiveDateTimeUtc = serviceProvider.GetRequiredService().LastActiveDateTimeUtc; - try - { - await InvokeShutdownAsync(shellSettings, shellHost); - } - catch (Exception e) - { - logger?.LogError( - e, - "Shutting down \"{ShellName}\" because of idle timeout failed with the following exception. Another shutdown will be attempted.", - shellSettings?.Name); + if (lastActiveDateTimeUtc.AddMinutes(maxIdleMinutes) <= clock?.UtcNow) + { + var logger = serviceProvider.GetRequiredService>(); - // If the ReleaseShellContextAsync() fails (which can happen with a DB error: then the transaction - // commits triggered by the dispose will fail) then while the tenant is unavailable the shell is still - // active in a failed state. So first we need to correctly start the tenant, then shut it down for good. + logger?.LogWarning("Shutting down tenant \"{ShellName}\" because of idle timeout.", shellSettings.Name); - var shellSettingsManager = serviceProvider.GetService(); + var shellHost = serviceProvider.GetRequiredService(); - await InvokeRestartAsync(shellSettingsManager, shellHost, shellSettings); - await InvokeShutdownAsync(shellSettings, shellHost); - } + await shellHost.ReleaseShellContextAsync(shellSettings, eventSource: false); } } - - private static Task InvokeShutdownAsync(ShellSettings shellSettings, IShellHost shellHost) => - shellHost.ReleaseShellContextAsync(shellSettings); - - private static async Task InvokeRestartAsync( - IShellSettingsManager shellSettingsManager, - IShellHost shellHost, - ShellSettings shellSettings) - { - await shellSettingsManager.SaveSettingsAsync(shellSettings); - await shellHost.UpdateShellSettingsAsync(shellSettings); - } } diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs index accb8573..37d50808 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs @@ -25,7 +25,7 @@ public override void Configure( IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) => - app.UseMiddleware(); + app.UseMiddleware(); public override void ConfigureServices(IServiceCollection services) {