-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app): move app init logic outside of LifecycleService to use els…
…ewhere
- Loading branch information
Showing
4 changed files
with
154 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
using Serilog; | ||
|
||
namespace Sitko.Core.App; | ||
|
||
public class ApplicationLifecycle( | ||
IApplicationContext context, | ||
IServiceProvider provider, | ||
IEnumerable<ApplicationModuleRegistration> applicationModuleRegistrations, | ||
ILogger<ApplicationLifecycle> logger) | ||
: IApplicationLifecycle | ||
{ | ||
private readonly IReadOnlyList<ApplicationModuleRegistration> enabledModules = | ||
ModulesHelper.GetEnabledModuleRegistrations(context, applicationModuleRegistrations); | ||
|
||
public async Task StartingAsync(CancellationToken cancellationToken) | ||
{ | ||
await using var scope = provider.CreateAsyncScope(); | ||
|
||
foreach (var enabledModule in enabledModules) | ||
{ | ||
var shouldContinue = await enabledModule.GetInstance() | ||
.OnBeforeRunAsync(context, scope.ServiceProvider); | ||
if (!shouldContinue) | ||
{ | ||
Environment.Exit(0); | ||
return; | ||
} | ||
} | ||
|
||
logger.LogInformation("Check required modules"); | ||
var modulesCheckSuccess = true; | ||
foreach (var registration in enabledModules) | ||
{ | ||
var result = | ||
registration.CheckRequiredModules(context, | ||
enabledModules.Select(r => r.Type).ToArray()); | ||
if (!result.isSuccess) | ||
{ | ||
foreach (var missingModule in result.missingModules) | ||
{ | ||
Log.Information("Required module {MissingModule} for module {Type} is not registered", | ||
missingModule, registration.Type); | ||
} | ||
|
||
modulesCheckSuccess = false; | ||
} | ||
} | ||
|
||
if (!modulesCheckSuccess) | ||
{ | ||
throw new InvalidOperationException("Check required modules failed"); | ||
} | ||
|
||
logger.LogInformation("Init modules"); | ||
|
||
foreach (var configurationModule in enabledModules.Select(module => module.GetInstance()) | ||
.OfType<IConfigurationModule>()) | ||
{ | ||
configurationModule.CheckConfiguration(context, scope.ServiceProvider); | ||
} | ||
|
||
foreach (var registration in enabledModules) | ||
{ | ||
logger.LogInformation("Init module {Module}", registration.Type); | ||
await registration.InitAsync(context, scope.ServiceProvider); | ||
} | ||
|
||
foreach (var enabledModule in enabledModules) | ||
{ | ||
var shouldContinue = | ||
await enabledModule.GetInstance().OnAfterRunAsync(context, scope.ServiceProvider); | ||
if (!shouldContinue) | ||
{ | ||
Environment.Exit(0); | ||
} | ||
} | ||
} | ||
|
||
public async Task StartedAsync(CancellationToken cancellationToken) | ||
{ | ||
foreach (var moduleRegistration in enabledModules) | ||
{ | ||
try | ||
{ | ||
await moduleRegistration.ApplicationStarted(context, provider); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error on application started hook in module {Module}: {ErrorText}", | ||
moduleRegistration.Type, | ||
ex.ToString()); | ||
} | ||
} | ||
} | ||
|
||
public async Task StoppingAsync(CancellationToken cancellationToken) | ||
{ | ||
foreach (var moduleRegistration in enabledModules) | ||
{ | ||
try | ||
{ | ||
await moduleRegistration.ApplicationStopping(context, provider); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error on application stopping hook in module {Module}: {ErrorText}", | ||
moduleRegistration.Type, | ||
ex.ToString()); | ||
} | ||
} | ||
} | ||
|
||
public async Task StoppedAsync(CancellationToken cancellationToken) | ||
{ | ||
foreach (var moduleRegistration in enabledModules) | ||
{ | ||
try | ||
{ | ||
await moduleRegistration.ApplicationStopped(context, provider); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error on application stopped hook in module {Module}: {ErrorText}", | ||
moduleRegistration.Type, | ||
ex.ToString()); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,22 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Serilog; | ||
using Sitko.Core.App.Logging; | ||
using Microsoft.Extensions.Hosting; | ||
|
||
namespace Sitko.Core.App; | ||
|
||
internal class HostedLifecycleService : IHostedLifecycleService | ||
internal class HostedLifecycleService(IApplicationLifecycle lifecycle) : IHostedLifecycleService | ||
{ | ||
private readonly ILogger<HostedLifecycleService> logger; | ||
private readonly IApplicationContext applicationContext; | ||
private readonly IServiceProvider serviceProvider; | ||
|
||
|
||
private readonly IReadOnlyList<ApplicationModuleRegistration> enabledModules; | ||
|
||
public HostedLifecycleService(ILogger<HostedLifecycleService> logger, IApplicationContext applicationContext, | ||
IServiceProvider serviceProvider, IEnumerable<ApplicationModuleRegistration> applicationModuleRegistrations) | ||
{ | ||
this.logger = logger; | ||
this.applicationContext = applicationContext; | ||
this.serviceProvider = serviceProvider; | ||
enabledModules = | ||
ModulesHelper.GetEnabledModuleRegistrations(applicationContext, applicationModuleRegistrations); | ||
} | ||
|
||
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; | ||
|
||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; | ||
|
||
public async Task StartingAsync(CancellationToken cancellationToken) | ||
{ | ||
await using var scope = serviceProvider.CreateAsyncScope(); | ||
|
||
foreach (var enabledModule in enabledModules) | ||
{ | ||
var shouldContinue = await enabledModule.GetInstance() | ||
.OnBeforeRunAsync(applicationContext, scope.ServiceProvider); | ||
if (!shouldContinue) | ||
{ | ||
Environment.Exit(0); | ||
return; | ||
} | ||
} | ||
|
||
logger.LogInformation("Check required modules"); | ||
var modulesCheckSuccess = true; | ||
foreach (var registration in enabledModules) | ||
{ | ||
var result = | ||
registration.CheckRequiredModules(applicationContext, | ||
enabledModules.Select(r => r.Type).ToArray()); | ||
if (!result.isSuccess) | ||
{ | ||
foreach (var missingModule in result.missingModules) | ||
{ | ||
Log.Information( | ||
$"Required module {missingModule} for module {registration.Type} is not registered"); | ||
} | ||
|
||
modulesCheckSuccess = false; | ||
} | ||
} | ||
|
||
if (!modulesCheckSuccess) | ||
{ | ||
throw new InvalidOperationException("Check required modules failed"); | ||
} | ||
|
||
logger.LogInformation("Init modules"); | ||
|
||
foreach (var configurationModule in enabledModules.Select(module => module.GetInstance()) | ||
.OfType<IConfigurationModule>()) | ||
{ | ||
configurationModule.CheckConfiguration(applicationContext, scope.ServiceProvider); | ||
} | ||
|
||
foreach (var registration in enabledModules) | ||
{ | ||
logger.LogInformation("Init module {Module}", registration.Type); | ||
await registration.InitAsync(applicationContext, scope.ServiceProvider); | ||
} | ||
|
||
foreach (var enabledModule in enabledModules) | ||
{ | ||
var shouldContinue = | ||
await enabledModule.GetInstance().OnAfterRunAsync(applicationContext, scope.ServiceProvider); | ||
if (!shouldContinue) | ||
{ | ||
Environment.Exit(0); | ||
} | ||
} | ||
} | ||
public Task StartingAsync(CancellationToken cancellationToken) => | ||
lifecycle.StartingAsync(cancellationToken); | ||
|
||
public async Task StartedAsync(CancellationToken cancellationToken) | ||
{ | ||
foreach (var moduleRegistration in enabledModules) | ||
{ | ||
try | ||
{ | ||
await moduleRegistration.ApplicationStarted(applicationContext, serviceProvider); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error on application started hook in module {Module}: {ErrorText}", | ||
moduleRegistration.Type, | ||
ex.ToString()); | ||
} | ||
} | ||
} | ||
public Task StartedAsync(CancellationToken cancellationToken) => | ||
lifecycle.StartedAsync(cancellationToken); | ||
|
||
public async Task StoppingAsync(CancellationToken cancellationToken) | ||
{ | ||
foreach (var moduleRegistration in enabledModules) | ||
{ | ||
try | ||
{ | ||
await moduleRegistration.ApplicationStopping(applicationContext, serviceProvider); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error on application stopping hook in module {Module}: {ErrorText}", | ||
moduleRegistration.Type, | ||
ex.ToString()); | ||
} | ||
} | ||
} | ||
public Task StoppingAsync(CancellationToken cancellationToken) => | ||
lifecycle.StoppingAsync(cancellationToken); | ||
|
||
public async Task StoppedAsync(CancellationToken cancellationToken) | ||
{ | ||
foreach (var moduleRegistration in enabledModules) | ||
{ | ||
try | ||
{ | ||
await moduleRegistration.ApplicationStopped(applicationContext, serviceProvider); | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger.LogError(ex, "Error on application stopped hook in module {Module}: {ErrorText}", | ||
moduleRegistration.Type, | ||
ex.ToString()); | ||
} | ||
} | ||
} | ||
public Task StoppedAsync(CancellationToken cancellationToken) => | ||
lifecycle.StoppedAsync(cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Sitko.Core.App; | ||
|
||
public interface IApplicationLifecycle | ||
{ | ||
Task StartingAsync(CancellationToken cancellationToken); | ||
|
||
Task StartedAsync(CancellationToken cancellationToken); | ||
|
||
Task StoppingAsync(CancellationToken cancellationToken); | ||
|
||
Task StoppedAsync(CancellationToken cancellationToken); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters