V10: Use FireAndForget when logging install (#12658)

* Use FireAndForget when logging install

* Obsolete constructor

Co-authored-by: Zeegaan <nge@umbraco.dk>
This commit is contained in:
Mole
2022-07-05 15:17:45 +02:00
committed by GitHub
parent 22577163ba
commit be38fb41ad
4 changed files with 89 additions and 1 deletions

View File

@@ -0,0 +1,41 @@
using Microsoft.Extensions.Logging;
namespace Umbraco.Cms.Core;
public class FireAndForgetRunner : IFireAndForgetRunner
{
private readonly ILogger<FireAndForgetRunner> _logger;
public FireAndForgetRunner(ILogger<FireAndForgetRunner> logger) => _logger = logger;
public void RunFireAndForget(Func<Task> task) => ExecuteBackgroundTask(task);
private Task ExecuteBackgroundTask(Func<Task> fn)
{
// it is also possible to use UnsafeQueueUserWorkItem which does not flow the execution context,
// however that seems more difficult to use for async operations.
// Do not flow AsyncLocal to the child thread
using (ExecutionContext.SuppressFlow())
{
// NOTE: ConfigureAwait(false) is irrelevant here, it is not needed because this is not being
// awaited. ConfigureAwait(false) is only relevant when awaiting to prevent the SynchronizationContext
// (very different from the ExecutionContext!) from running the continuation on the calling thread.
return Task.Run(LoggingWrapper(fn));
}
}
private Func<Task> LoggingWrapper(Func<Task> fn) =>
async () =>
{
try
{
await fn();
}
catch (Exception e)
{
_logger.LogError(e, "Exception thrown in a background thread");
}
};
}

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Core;
public interface IFireAndForgetRunner
{
void RunFireAndForget(Func<Task> task);
}

View File

@@ -219,6 +219,8 @@ public static partial class UmbracoBuilderExtensions
// Services required to run background jobs (with out the handler)
builder.Services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
builder.Services.AddTransient<IFireAndForgetRunner, FireAndForgetRunner>();
return builder;
}

View File

@@ -1,3 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
@@ -9,6 +10,7 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
@@ -24,8 +26,35 @@ namespace Umbraco.Cms.Infrastructure.Install
private readonly ICookieManager _cookieManager;
private readonly IUserAgentProvider _userAgentProvider;
private readonly IUmbracoDatabaseFactory _umbracoDatabaseFactory;
private readonly IFireAndForgetRunner _fireAndForgetRunner;
private InstallationType? _installationType;
public InstallHelper(
DatabaseBuilder databaseBuilder,
ILogger<InstallHelper> logger,
IUmbracoVersion umbracoVersion,
IOptionsMonitor<ConnectionStrings> connectionStrings,
IInstallationService installationService,
ICookieManager cookieManager,
IUserAgentProvider userAgentProvider,
IUmbracoDatabaseFactory umbracoDatabaseFactory,
IFireAndForgetRunner fireAndForgetRunner)
{
_logger = logger;
_umbracoVersion = umbracoVersion;
_databaseBuilder = databaseBuilder;
_connectionStrings = connectionStrings;
_installationService = installationService;
_cookieManager = cookieManager;
_userAgentProvider = userAgentProvider;
_umbracoDatabaseFactory = umbracoDatabaseFactory;
_fireAndForgetRunner = fireAndForgetRunner;
// We need to initialize the type already, as we can't detect later, if the connection string is added on the fly.
GetInstallationType();
}
[Obsolete("Please use constructor that takes an IFireAndForgetRunner instead, scheduled for removal in Umbraco 12")]
public InstallHelper(
DatabaseBuilder databaseBuilder,
ILogger<InstallHelper> logger,
@@ -35,6 +64,16 @@ namespace Umbraco.Cms.Infrastructure.Install
ICookieManager cookieManager,
IUserAgentProvider userAgentProvider,
IUmbracoDatabaseFactory umbracoDatabaseFactory)
: this(
databaseBuilder,
logger,
umbracoVersion,
connectionStrings,
installationService,
cookieManager,
userAgentProvider,
umbracoDatabaseFactory,
StaticServiceProvider.Instance.GetRequiredService<IFireAndForgetRunner>())
{
_logger = logger;
_umbracoVersion = umbracoVersion;
@@ -87,7 +126,7 @@ namespace Umbraco.Cms.Infrastructure.Install
userAgent: userAgent,
dbProvider: dbProvider);
await _installationService.LogInstall(installLog);
_fireAndForgetRunner.RunFireAndForget(() => _installationService.LogInstall(installLog));
}
catch (Exception ex)
{