Add UmbracoApplicationStartedNotification and UmbracoApplicationStoppedNotification (#11857)

* Add UmbracoApplicationStartedNotification and UmbracoApplicationStoppedNotification

* Include cancellation token when publishing unattended install/upgrade notifications
This commit is contained in:
Ronald Barendse
2022-01-18 13:58:14 +01:00
committed by GitHub
parent bf166225de
commit 364b8f1c72
5 changed files with 99 additions and 30 deletions

View File

@@ -0,0 +1,9 @@
namespace Umbraco.Cms.Core.Notifications
{
/// <summary>
/// Notification that occurs when Umbraco has completely booted up and the request processing pipeline is configured.
/// </summary>
/// <seealso cref="Umbraco.Cms.Core.Notifications.INotification" />
public class UmbracoApplicationStartedNotification : INotification
{ }
}

View File

@@ -1,23 +1,23 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Notifications
{
/// <summary>
/// Notification that occurs at the very end of the Umbraco boot
/// process and after all <see cref="IComponent"/> initialize.
/// Notification that occurs at the very end of the Umbraco boot process (after all <see cref="IComponent" />s are initialized).
/// </summary>
/// <seealso cref="Umbraco.Cms.Core.Notifications.INotification" />
public class UmbracoApplicationStartingNotification : INotification
{
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoApplicationStartingNotification"/> class.
/// Initializes a new instance of the <see cref="UmbracoApplicationStartingNotification" /> class.
/// </summary>
/// <param name="runtimeLevel">The runtime level</param>
public UmbracoApplicationStartingNotification(RuntimeLevel runtimeLevel) => RuntimeLevel = runtimeLevel;
/// <summary>
/// Gets the runtime level of execution.
/// Gets the runtime level.
/// </summary>
/// <value>
/// The runtime level.
/// </value>
public RuntimeLevel RuntimeLevel { get; }
}
}

View File

@@ -0,0 +1,9 @@
namespace Umbraco.Cms.Core.Notifications
{
/// <summary>
/// Notification that occurs when Umbraco has completely shutdown.
/// </summary>
/// <seealso cref="Umbraco.Cms.Core.Notifications.INotification" />
public class UmbracoApplicationStoppedNotification : INotification
{ }
}

View File

@@ -1,4 +1,9 @@
namespace Umbraco.Cms.Core.Notifications
{
public class UmbracoApplicationStoppingNotification : INotification { }
/// <summary>
/// Notification that occurs when Umbraco is shutting down (after all <see cref="IComponent" />s are terminated).
/// </summary>
/// <seealso cref="Umbraco.Cms.Core.Notifications.INotification" />
public class UmbracoApplicationStoppingNotification : INotification
{ }
}

View File

@@ -2,6 +2,8 @@ using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration;
@@ -16,12 +18,13 @@ using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
using ComponentCollection = Umbraco.Cms.Core.Composing.ComponentCollection;
using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment;
namespace Umbraco.Cms.Infrastructure.Runtime
{
/// <inheritdoc />
public class CoreRuntime : IRuntime
{
private readonly ILogger<CoreRuntime> _logger;
private readonly ILoggerFactory _loggerFactory;
private readonly ComponentCollection _components;
private readonly IApplicationShutdownRegistry _applicationShutdownRegistry;
@@ -32,14 +35,16 @@ namespace Umbraco.Cms.Infrastructure.Runtime
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IServiceProvider _serviceProvider;
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly ILogger<CoreRuntime> _logger;
private CancellationToken _cancellationToken;
/// <summary>
/// Initializes a new instance of the <see cref="CoreRuntime"/> class.
/// Initializes a new instance of the <see cref="CoreRuntime" /> class.
/// </summary>
public CoreRuntime(
ILoggerFactory loggerFactory,
IRuntimeState state,
ILoggerFactory loggerFactory,
ComponentCollection components,
IApplicationShutdownRegistry applicationShutdownRegistry,
IProfilingLogger profilingLogger,
@@ -48,9 +53,11 @@ namespace Umbraco.Cms.Infrastructure.Runtime
IEventAggregator eventAggregator,
IHostingEnvironment hostingEnvironment,
IUmbracoVersion umbracoVersion,
IServiceProvider serviceProvider)
IServiceProvider serviceProvider,
IHostApplicationLifetime hostApplicationLifetime)
{
State = state;
_loggerFactory = loggerFactory;
_components = components;
_applicationShutdownRegistry = applicationShutdownRegistry;
@@ -61,6 +68,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
_hostingEnvironment = hostingEnvironment;
_umbracoVersion = umbracoVersion;
_serviceProvider = serviceProvider;
_hostApplicationLifetime = hostApplicationLifetime;
_logger = _loggerFactory.CreateLogger<CoreRuntime>();
}
@@ -76,23 +84,49 @@ namespace Umbraco.Cms.Infrastructure.Runtime
IUmbracoDatabaseFactory databaseFactory,
IEventAggregator eventAggregator,
IHostingEnvironment hostingEnvironment,
IUmbracoVersion umbracoVersion
):this(
loggerFactory,
state,
components,
applicationShutdownRegistry,
profilingLogger,
mainDom,
databaseFactory,
eventAggregator,
hostingEnvironment,
umbracoVersion,
null
)
{
IUmbracoVersion umbracoVersion,
IServiceProvider serviceProvider)
: this(
state,
loggerFactory,
components,
applicationShutdownRegistry,
profilingLogger,
mainDom,
databaseFactory,
eventAggregator,
hostingEnvironment,
umbracoVersion,
serviceProvider,
serviceProvider?.GetRequiredService<IHostApplicationLifetime>())
{ }
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete]
public CoreRuntime(
ILoggerFactory loggerFactory,
IRuntimeState state,
ComponentCollection components,
IApplicationShutdownRegistry applicationShutdownRegistry,
IProfilingLogger profilingLogger,
IMainDom mainDom,
IUmbracoDatabaseFactory databaseFactory,
IEventAggregator eventAggregator,
IHostingEnvironment hostingEnvironment,
IUmbracoVersion umbracoVersion)
: this(
loggerFactory,
state,
components,
applicationShutdownRegistry,
profilingLogger,
mainDom,
databaseFactory,
eventAggregator,
hostingEnvironment,
umbracoVersion,
null)
{ }
/// <summary>
/// Gets the state of the Umbraco runtime.
@@ -103,13 +137,17 @@ namespace Umbraco.Cms.Infrastructure.Runtime
public async Task RestartAsync()
{
await StopAsync(_cancellationToken);
await _eventAggregator.PublishAsync(new UmbracoApplicationStoppedNotification(), _cancellationToken);
await StartAsync(_cancellationToken);
await _eventAggregator.PublishAsync(new UmbracoApplicationStartedNotification(), _cancellationToken);
}
/// <inheritdoc/>
public async Task StartAsync(CancellationToken cancellationToken)
{
// Store token, so we can re-use this during restart
_cancellationToken = cancellationToken;
StaticApplicationLogging.Initialize(_loggerFactory);
StaticServiceProvider.Instance = _serviceProvider;
@@ -130,6 +168,13 @@ namespace Umbraco.Cms.Infrastructure.Runtime
_logger.LogError(exception, msg);
};
// Add application started and stopped notifications (only on initial startup, not restarts)
if (_hostApplicationLifetime.ApplicationStarted.IsCancellationRequested == false)
{
_hostApplicationLifetime.ApplicationStarted.Register(() => _eventAggregator.Publish(new UmbracoApplicationStartedNotification()));
_hostApplicationLifetime.ApplicationStopped.Register(() => _eventAggregator.Publish(new UmbracoApplicationStoppedNotification()));
}
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
AcquireMainDom();
@@ -137,7 +182,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
await _eventAggregator.PublishAsync(new UmbracoApplicationMainDomAcquiredNotification(), cancellationToken);
// notify for unattended install
await _eventAggregator.PublishAsync(new RuntimeUnattendedInstallNotification());
await _eventAggregator.PublishAsync(new RuntimeUnattendedInstallNotification(), cancellationToken);
DetermineRuntimeLevel();
if (!State.UmbracoCanBoot())
@@ -153,7 +198,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
// if level is Run and reason is UpgradeMigrations, that means we need to perform an unattended upgrade
var unattendedUpgradeNotification = new RuntimeUnattendedUpgradeNotification();
await _eventAggregator.PublishAsync(unattendedUpgradeNotification);
await _eventAggregator.PublishAsync(unattendedUpgradeNotification, cancellationToken);
switch (unattendedUpgradeNotification.UnattendedUpgradeResult)
{
case RuntimeUnattendedUpgradeNotification.UpgradeResult.HasErrors:
@@ -161,6 +206,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
{
throw new InvalidOperationException($"Unattended upgrade result was {RuntimeUnattendedUpgradeNotification.UpgradeResult.HasErrors} but no {nameof(BootFailedException)} was registered");
}
// we cannot continue here, the exception will be rethrown by BootFailedMiddelware
return;
case RuntimeUnattendedUpgradeNotification.UpgradeResult.CoreUpgradeComplete: