159 lines
6.7 KiB
C#
159 lines
6.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using Umbraco.Core;
|
|
using Umbraco.Core.Composing;
|
|
using Umbraco.Core.Configuration;
|
|
using Umbraco.Core.Configuration.HealthChecks;
|
|
using Umbraco.Core.Configuration.UmbracoSettings;
|
|
using Umbraco.Core.Logging;
|
|
using Umbraco.Core.Scoping;
|
|
using Umbraco.Core.Services;
|
|
using Umbraco.Web.HealthCheck;
|
|
using Umbraco.Web.Routing;
|
|
|
|
namespace Umbraco.Web.Scheduling
|
|
{
|
|
internal sealed class SchedulerComponent : IComponent
|
|
{
|
|
private readonly IRuntimeState _runtime;
|
|
private readonly IContentService _contentService;
|
|
private readonly IAuditService _auditService;
|
|
private readonly IProfilingLogger _logger;
|
|
private readonly IScopeProvider _scopeProvider;
|
|
private readonly HealthCheckCollection _healthChecks;
|
|
private readonly HealthCheckNotificationMethodCollection _notifications;
|
|
private readonly IUmbracoContextFactory _umbracoContextFactory;
|
|
|
|
private BackgroundTaskRunner<IBackgroundTask> _keepAliveRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _publishingRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _tasksRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _scrubberRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _healthCheckRunner;
|
|
|
|
private bool _started;
|
|
private object _locker = new object();
|
|
private IBackgroundTask[] _tasks;
|
|
|
|
public SchedulerComponent(IRuntimeState runtime,
|
|
IContentService contentService, IAuditService auditService,
|
|
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
|
|
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger)
|
|
{
|
|
_runtime = runtime;
|
|
_contentService = contentService;
|
|
_auditService = auditService;
|
|
_scopeProvider = scopeProvider;
|
|
_logger = logger;
|
|
_umbracoContextFactory = umbracoContextFactory;
|
|
|
|
_healthChecks = healthChecks;
|
|
_notifications = notifications;
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
// backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly
|
|
_keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", _logger);
|
|
_publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", _logger);
|
|
_tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", _logger);
|
|
_scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", _logger);
|
|
_healthCheckRunner = new BackgroundTaskRunner<IBackgroundTask>("HealthCheckNotifier", _logger);
|
|
|
|
// we will start the whole process when a successful request is made
|
|
UmbracoModule.RouteAttempt += RegisterBackgroundTasksOnce;
|
|
}
|
|
|
|
public void Terminate()
|
|
{
|
|
// the AppDomain / maindom / whatever takes care of stopping background task runners
|
|
}
|
|
|
|
private void RegisterBackgroundTasksOnce(object sender, RoutableAttemptEventArgs e)
|
|
{
|
|
switch (e.Outcome)
|
|
{
|
|
case EnsureRoutableOutcome.IsRoutable:
|
|
case EnsureRoutableOutcome.NotDocumentRequest:
|
|
UmbracoModule.RouteAttempt -= RegisterBackgroundTasksOnce;
|
|
RegisterBackgroundTasks();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void RegisterBackgroundTasks()
|
|
{
|
|
LazyInitializer.EnsureInitialized(ref _tasks, ref _started, ref _locker, () =>
|
|
{
|
|
_logger.Debug<SchedulerComponent>("Initializing the scheduler");
|
|
var settings = Current.Configs.Settings();
|
|
|
|
var tasks = new List<IBackgroundTask>();
|
|
|
|
tasks.Add(RegisterKeepAlive());
|
|
tasks.Add(RegisterScheduledPublishing());
|
|
tasks.Add(RegisterLogScrubber(settings));
|
|
|
|
var healthCheckConfig = Current.Configs.HealthChecks();
|
|
if (healthCheckConfig.NotificationSettings.Enabled)
|
|
tasks.Add(RegisterHealthCheckNotifier(healthCheckConfig, _healthChecks, _notifications, _logger));
|
|
|
|
return tasks.ToArray();
|
|
});
|
|
}
|
|
|
|
private IBackgroundTask RegisterKeepAlive()
|
|
{
|
|
// ping/keepalive
|
|
// on all servers
|
|
var task = new KeepAlive(_keepAliveRunner, 60000, 300000, _runtime, _logger);
|
|
_keepAliveRunner.TryAdd(task);
|
|
return task;
|
|
}
|
|
|
|
private IBackgroundTask RegisterScheduledPublishing()
|
|
{
|
|
// scheduled publishing/unpublishing
|
|
// install on all, will only run on non-replica servers
|
|
var task = new ScheduledPublishing(_publishingRunner, 60000, 60000, _runtime, _contentService, _umbracoContextFactory, _logger);
|
|
_publishingRunner.TryAdd(task);
|
|
return task;
|
|
}
|
|
|
|
private IBackgroundTask RegisterHealthCheckNotifier(IHealthChecks healthCheckConfig,
|
|
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
|
|
IProfilingLogger logger)
|
|
{
|
|
// If first run time not set, start with just small delay after application start
|
|
int delayInMilliseconds;
|
|
if (string.IsNullOrEmpty(healthCheckConfig.NotificationSettings.FirstRunTime))
|
|
{
|
|
delayInMilliseconds = 60000;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise start at scheduled time
|
|
delayInMilliseconds = DateTime.Now.PeriodicMinutesFrom(healthCheckConfig.NotificationSettings.FirstRunTime) * 60 * 1000;
|
|
if (delayInMilliseconds < 60000)
|
|
{
|
|
delayInMilliseconds = 60000;
|
|
}
|
|
}
|
|
|
|
var periodInMilliseconds = healthCheckConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000;
|
|
var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger);
|
|
_healthCheckRunner.TryAdd(task);
|
|
return task;
|
|
}
|
|
|
|
private IBackgroundTask RegisterLogScrubber(IUmbracoSettingsSection settings)
|
|
{
|
|
// log scrubbing
|
|
// install on all, will only run on non-replica servers
|
|
var task = new LogScrubber(_scrubberRunner, 60000, LogScrubber.GetLogScrubbingInterval(settings, _logger), _runtime, _auditService, settings, _scopeProvider, _logger);
|
|
_scrubberRunner.TryAdd(task);
|
|
return task;
|
|
}
|
|
}
|
|
}
|