From 79c1e203021534ed977395b54c521c4f535b2bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 4 Oct 2022 15:29:05 +0200 Subject: [PATCH 1/5] Changing feature name to use "ShutDown" instead of "Disable" since disabling a tenant means something else --- .../Constants/FeatureNames.cs | 4 ++-- .../Manifest.cs | 6 +++--- .../Readme.md | 18 ++++++++++++++++-- .../Services/IdleShutdownTask.cs | 2 +- .../Startup.cs | 6 +++--- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Constants/FeatureNames.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Constants/FeatureNames.cs index fdb26b18..a7b534cc 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Constants/FeatureNames.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Constants/FeatureNames.cs @@ -1,8 +1,8 @@ -namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Constants; +namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Constants; public static class FeatureNames { private const string Module = "Lombiq.Hosting.Tenants.IdleTenantManagement"; - public const string DisableIdleTenants = Module + "." + nameof(DisableIdleTenants); + public const string ShutDownIdleTenants = Module + "." + nameof(ShutDownIdleTenants); } diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Manifest.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Manifest.cs index c2e2041e..127c4f00 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Manifest.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Manifest.cs @@ -10,9 +10,9 @@ )] [assembly: Feature( - Id = DisableIdleTenants, - Name = "Lombiq Hosting - Idle Tenant Management - Disable Idle Tenants", - Description = "Disable tenants not receiving requests after a configured amount of time.", + Id = ShutDownIdleTenants, + Name = "Lombiq Hosting - Idle Tenant Management - Shut Down Idle Tenants", + Description = "Shut down tenants not receiving requests after a configured amount of time to conserve computing resources.", Category = "Hosting", Priority = "9999", IsAlwaysEnabled = true diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md b/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md index 22f871bb..24d5a616 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md @@ -17,7 +17,21 @@ This feature is available on any tenant. The maximum idle time can be set in the ```csharp public void ConfigureServices(IServiceCollection services) => services.AddOrchardCms( - builder => builder.AddTenantFeatures(Lombiq.Hosting.Tenants.IdleTenantManagement.Constants.FeatureNames.DisableIdleTenants)); + builder => builder.AddTenantFeatures(Lombiq.Hosting.Tenants.IdleTenantManagement.Constants.FeatureNames.ShutDownIdleTenants)); ``` -**NOTE:** This way the feature will also be enabled on the Default tenant. You may not want to use this feature on the default tenant. +**NOTE:** This way the feature will also be enabled on the Default tenant. You may not want to use this feature on the default tenant, so configure the corresponding `MaxIdleMinutes` as `0`. You can do this in an _appsettings.json_ file like this (see [the docs](https://docs.orchardcore.net/en/latest/docs/reference/core/Configuration/) for more details): + +```json +{ + "OrchardCore": { + "Default": { + "Lombiq_Hosting_Tenants_IdleTenantManagement": { + "IdleMinutesOptions": { + "MaxIdleMinutes": 0 + } + } + } + } +} +``` diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs index f1880dcb..075670e8 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs @@ -11,7 +11,7 @@ namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Services; -[BackgroundTask(Schedule = "* * * * *", Description = "Disable Idle Tenants.")] +[BackgroundTask(Schedule = "* * * * *", Description = "Shut down idle tenants.")] public class IdleShutdownTask : IBackgroundTask { public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken) diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs index c76aa64c..7f8c544f 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs @@ -13,12 +13,12 @@ namespace Lombiq.Hosting.Tenants.IdleTenantManagement; -[Feature(FeatureNames.DisableIdleTenants)] -public class DisableIdleTenantsStartup : StartupBase +[Feature(FeatureNames.ShutDownIdleTenants)] +public class ShutDownIdleTenantsStartup : StartupBase { private readonly IShellConfiguration _shellConfiguration; - public DisableIdleTenantsStartup(IShellConfiguration shellConfiguration) => + public ShutDownIdleTenantsStartup(IShellConfiguration shellConfiguration) => _shellConfiguration = shellConfiguration; public override void Configure( From a4c47507c6b2c61416a8687c5f28e3c9b918b691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 4 Oct 2022 15:29:13 +0200 Subject: [PATCH 2/5] Code styling --- Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs index 7f8c544f..aea2d487 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs @@ -1,4 +1,4 @@ -using Lombiq.Hosting.Tenants.IdleTenantManagement.Constants; +using Lombiq.Hosting.Tenants.IdleTenantManagement.Constants; using Lombiq.Hosting.Tenants.IdleTenantManagement.Middlewares; using Lombiq.Hosting.Tenants.IdleTenantManagement.Models; using Lombiq.Hosting.Tenants.IdleTenantManagement.Services; @@ -25,7 +25,7 @@ public override void Configure( IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) => - app.UseMiddleware(); + app.UseMiddleware(); public override void ConfigureServices(IServiceCollection services) { From dcdb594430d4a7d3b3094cb213516f57fefcb340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 4 Oct 2022 15:30:32 +0200 Subject: [PATCH 3/5] Only resolving services when needed --- .../Services/IdleShutdownTask.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs index 075670e8..dbfb2629 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs @@ -17,19 +17,19 @@ public class IdleShutdownTask : IBackgroundTask public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken) { var clock = serviceProvider.GetService(); - var shellSettings = serviceProvider.GetService(); - var logger = serviceProvider.GetService>(); var lastActiveTimeAccessor = serviceProvider.GetService(); - var shellSettingsManager = serviceProvider.GetService(); var shellHost = serviceProvider.GetService(); - var options = serviceProvider.GetService>(); + var options = serviceProvider.GetService>(); var maxIdleMinutes = options.Value.MaxIdleMinutes; if (maxIdleMinutes <= 0) return; if (lastActiveTimeAccessor.LastActiveDateTimeUtc.AddMinutes(maxIdleMinutes) <= clock?.UtcNow) { + var shellSettings = serviceProvider.GetService(); + var logger = serviceProvider.GetService>(); + logger?.LogInformation("Shutting down tenant \"{ShellName}\" because of idle timeout.", shellSettings?.Name); try @@ -48,6 +48,8 @@ public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToke // still active in a failed state. So first we need to correctly start the tenant, then shut it // down for good. + var shellSettingsManager = serviceProvider.GetService(); + await InvokeRestartAsync(shellSettingsManager, shellHost, shellSettings); await InvokeShutdownAsync(shellSettings, shellHost); } From e546923e53ad622eee235b6b5da2c594aaa072b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 4 Oct 2022 15:30:47 +0200 Subject: [PATCH 4/5] Code styling --- .../Services/IdleShutdownTask.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs index dbfb2629..0ebebb2e 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs @@ -44,9 +44,8 @@ public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToke shellSettings?.Name); // 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. + // 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. var shellSettingsManager = serviceProvider.GetService(); From 5e8b7cbf7757e659a300d4ba813343fa0788da7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 4 Oct 2022 15:34:32 +0200 Subject: [PATCH 5/5] More appropriate name for option --- .../Extensions/IdleTenantManagementExtensions.cs | 4 ++-- .../Models/IdleMinutesOptions.cs | 9 --------- .../Models/IdleShutdownOptions.cs | 9 +++++++++ Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md | 2 +- .../Services/IdleShutdownTask.cs | 2 +- Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleMinutesOptions.cs create mode 100644 Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleShutdownOptions.cs diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs index 0427f383..43dddf67 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement.Tests.UI/Extensions/IdleTenantManagementExtensions.cs @@ -13,7 +13,7 @@ public static void SetMaxIdleMinutesAndLoggingForUITest( (_, argumentsBuilder) => { argumentsBuilder - .Add("--OrchardCore:Lombiq_Hosting_Tenants_IdleTenantManagement:IdleMinutesOptions:MaxIdleMinutes") + .Add("--OrchardCore:Lombiq_Hosting_Tenants_IdleTenantManagement:IdleShutdownOptions:MaxIdleMinutes") .Add("1"); argumentsBuilder @@ -26,5 +26,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 \"Default\" because of idle timeout."); } diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleMinutesOptions.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleMinutesOptions.cs deleted file mode 100644 index b6f1b791..00000000 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleMinutesOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Models; - -public class IdleMinutesOptions -{ - /// - /// Gets or sets the maximum amount of time before the tenant shuts down. - /// - public int MaxIdleMinutes { get; set; } = 30; -} diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleShutdownOptions.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleShutdownOptions.cs new file mode 100644 index 00000000..7803ff3a --- /dev/null +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Models/IdleShutdownOptions.cs @@ -0,0 +1,9 @@ +namespace Lombiq.Hosting.Tenants.IdleTenantManagement.Models; + +public class IdleShutdownOptions +{ + /// + /// Gets or sets the maximum amount of idle time before the tenant shuts down. + /// + public int MaxIdleMinutes { get; set; } = 30; +} diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md b/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md index 24d5a616..c9173739 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Readme.md @@ -27,7 +27,7 @@ public void ConfigureServices(IServiceCollection services) => "OrchardCore": { "Default": { "Lombiq_Hosting_Tenants_IdleTenantManagement": { - "IdleMinutesOptions": { + "IdleShutdownOptions": { "MaxIdleMinutes": 0 } } diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs index 0ebebb2e..60e37ecc 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Services/IdleShutdownTask.cs @@ -20,7 +20,7 @@ public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToke var lastActiveTimeAccessor = serviceProvider.GetService(); var shellHost = serviceProvider.GetService(); - var options = serviceProvider.GetService>(); + var options = serviceProvider.GetService>(); var maxIdleMinutes = options.Value.MaxIdleMinutes; if (maxIdleMinutes <= 0) return; diff --git a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs index aea2d487..accb8573 100644 --- a/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs +++ b/Lombiq.Hosting.Tenants.IdleTenantManagement/Startup.cs @@ -33,9 +33,9 @@ public override void ConfigureServices(IServiceCollection services) services.AddSingleton(); // Idle Minutes Settings - services.Configure(options => + services.Configure(options => _shellConfiguration - .GetSection("Lombiq_Hosting_Tenants_IdleTenantManagement:IdleMinutesOptions") + .GetSection("Lombiq_Hosting_Tenants_IdleTenantManagement:IdleShutdownOptions") .Bind(options)); } }