Merge pull request #12153 from vsilvar/v9/bugfix/12022_recurring_hosted_service_scope_leak
Fixes RecurringHostServices leaking the execution context / ambient scope
This commit is contained in:
committed by
Nikolaj Geisle
parent
04c292f167
commit
0d836875c7
@@ -32,7 +32,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IContentVersionService service,
|
||||
IMainDom mainDom,
|
||||
IServerRoleAccessor serverRoleAccessor)
|
||||
: base(TimeSpan.FromHours(1), TimeSpan.FromMinutes(3))
|
||||
: base(logger, TimeSpan.FromHours(1), TimeSpan.FromMinutes(1))
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_logger = logger;
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IProfilingLogger profilingLogger,
|
||||
ICronTabParser cronTabParser)
|
||||
: base(
|
||||
logger,
|
||||
healthChecksSettings.Value.Notification.Period,
|
||||
healthChecksSettings.Value.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay))
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IProfilingLogger profilingLogger,
|
||||
IServerRoleAccessor serverRegistrar,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
: base(TimeSpan.FromMinutes(5), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromMinutes(5), DefaultDelay)
|
||||
{
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_mainDom = mainDom;
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IScopeProvider scopeProvider,
|
||||
ILogger<LogScrubber> logger,
|
||||
IProfilingLogger profilingLogger)
|
||||
: base(TimeSpan.FromHours(4), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromHours(4), DefaultDelay)
|
||||
{
|
||||
_mainDom = mainDom;
|
||||
_serverRegistrar = serverRegistrar;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
{
|
||||
@@ -21,6 +22,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// </summary>
|
||||
protected static readonly TimeSpan DefaultDelay = TimeSpan.FromMinutes(3);
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private TimeSpan _period;
|
||||
private readonly TimeSpan _delay;
|
||||
private Timer _timer;
|
||||
@@ -29,10 +31,12 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RecurringHostedServiceBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="period">Timepsan representing how often the task should recur.</param>
|
||||
/// <param name="delay">Timespan represeting the initial delay after application start-up before the first run of the task occurs.</param>
|
||||
protected RecurringHostedServiceBase(TimeSpan period, TimeSpan delay)
|
||||
/// <param name="logger">Logger.</param>
|
||||
/// <param name="period">Timespan representing how often the task should recur.</param>
|
||||
/// <param name="delay">Timespan representing the initial delay after application start-up before the first run of the task occurs.</param>
|
||||
protected RecurringHostedServiceBase(ILogger logger, TimeSpan period, TimeSpan delay)
|
||||
{
|
||||
_logger = logger;
|
||||
_period = period;
|
||||
_delay = delay;
|
||||
}
|
||||
@@ -40,7 +44,11 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// <inheritdoc/>
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_timer = new Timer(ExecuteAsync, null, (int)_delay.TotalMilliseconds, (int)_period.TotalMilliseconds);
|
||||
using (!ExecutionContext.IsFlowSuppressed() ? (IDisposable)ExecutionContext.SuppressFlow() : null)
|
||||
{
|
||||
_timer = new Timer(ExecuteAsync, null, (int)_delay.TotalMilliseconds, (int)_period.TotalMilliseconds);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -61,6 +69,10 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
// Hat-tip: https://stackoverflow.com/a/14207615/489433
|
||||
await PerformExecuteAsync(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unhandled exception in recurring hosted service {serviceName}.", GetType().Name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Resume now that the task is complete - Note we use period in both because we don't want to execute again after the delay.
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
public ReportSiteTask(
|
||||
ILogger<ReportSiteTask> logger,
|
||||
ITelemetryService telemetryService)
|
||||
: base(TimeSpan.FromDays(1), TimeSpan.FromMinutes(1))
|
||||
: base(logger, TimeSpan.FromDays(1), TimeSpan.FromMinutes(1))
|
||||
{
|
||||
_logger = logger;
|
||||
_telemetryService = telemetryService;
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
ILogger<ScheduledPublishing> logger,
|
||||
IServerMessenger serverMessenger,
|
||||
IScopeProvider scopeProvider)
|
||||
: base(TimeSpan.FromMinutes(1), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromMinutes(1), DefaultDelay)
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_mainDom = mainDom;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
/// <param name="logger">The typed logger.</param>
|
||||
/// <param name="globalSettings">The configuration for global settings.</param>
|
||||
public InstructionProcessTask(IRuntimeState runtimeState, IServerMessenger messenger, ILogger<InstructionProcessTask> logger, IOptions<GlobalSettings> globalSettings)
|
||||
: base(globalSettings.Value.DatabaseServerMessenger.TimeBetweenSyncOperations, TimeSpan.FromMinutes(1))
|
||||
: base(logger, globalSettings.Value.DatabaseServerMessenger.TimeBetweenSyncOperations, TimeSpan.FromMinutes(1))
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_messenger = messenger;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
ILogger<TouchServerTask> logger,
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
IServerRoleAccessor serverRoleAccessor)
|
||||
: base(globalSettings.Value.DatabaseServerRegistrar.WaitTimeBetweenCalls, TimeSpan.FromSeconds(15))
|
||||
: base(logger, globalSettings.Value.DatabaseServerRegistrar.WaitTimeBetweenCalls, TimeSpan.FromSeconds(15))
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_serverRegistrationService = serverRegistrationService ?? throw new ArgumentNullException(nameof(serverRegistrationService));
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// <param name="mainDom">Representation of the main application domain.</param>
|
||||
/// <param name="logger">The typed logger.</param>
|
||||
public TempFileCleanup(IIOHelper ioHelper, IMainDom mainDom, ILogger<TempFileCleanup> logger)
|
||||
: base(TimeSpan.FromMinutes(60), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromMinutes(60), DefaultDelay)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
_mainDom = mainDom;
|
||||
|
||||
@@ -247,6 +247,13 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
/// </summary>
|
||||
private bool TryDeserializeInstructions(CacheInstruction instruction, out JArray jsonInstructions)
|
||||
{
|
||||
if (instruction.Instructions is null)
|
||||
{
|
||||
_logger.LogError("Failed to deserialize instructions ({DtoId}: 'null').", instruction.Id);
|
||||
jsonInstructions = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
jsonInstructions = JsonConvert.DeserializeObject<JArray>(instruction.Instructions);
|
||||
|
||||
Reference in New Issue
Block a user