126 lines
5.7 KiB
C#
126 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.Threading;
|
|
using Umbraco.Core;
|
|
using Umbraco.Core.Configuration;
|
|
using Umbraco.Core.Configuration.HealthChecks;
|
|
using Umbraco.Core.Logging;
|
|
using Umbraco.Web.HealthCheck;
|
|
using Umbraco.Web.Routing;
|
|
|
|
namespace Umbraco.Web.Scheduling
|
|
{
|
|
/// <summary>
|
|
/// Used to do the scheduling for tasks, publishing, etc...
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// All tasks are run in a background task runner which is web aware and will wind down the task correctly instead of killing it completely when
|
|
/// the app domain shuts down.
|
|
/// </remarks>
|
|
internal sealed class Scheduler : ApplicationEventHandler
|
|
{
|
|
private BackgroundTaskRunner<IBackgroundTask> _keepAliveRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _publishingRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _tasksRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _scrubberRunner;
|
|
private BackgroundTaskRunner<IBackgroundTask> _healthCheckRunner;
|
|
private bool _started = false;
|
|
private object _locker = new object();
|
|
private IBackgroundTask[] _tasks;
|
|
|
|
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
|
|
{
|
|
if (umbracoApplication.Context == null)
|
|
return;
|
|
|
|
// backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly
|
|
_keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", applicationContext.ProfilingLogger.Logger);
|
|
_publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", applicationContext.ProfilingLogger.Logger);
|
|
_tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", applicationContext.ProfilingLogger.Logger);
|
|
_scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", applicationContext.ProfilingLogger.Logger);
|
|
_healthCheckRunner = new BackgroundTaskRunner<IBackgroundTask>("HealthCheckNotifier", applicationContext.ProfilingLogger.Logger);
|
|
|
|
//We will start the whole process when a successful request is made
|
|
UmbracoModule.RouteAttempt += UmbracoModuleRouteAttempt;
|
|
}
|
|
|
|
private void UmbracoModuleRouteAttempt(object sender, RoutableAttemptEventArgs e)
|
|
{
|
|
switch (e.Outcome)
|
|
{
|
|
case EnsureRoutableOutcome.IsRoutable:
|
|
case EnsureRoutableOutcome.NotDocumentRequest:
|
|
RegisterBackgroundTasks(e);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void RegisterBackgroundTasks(UmbracoRequestEventArgs e)
|
|
{
|
|
//remove handler, we're done
|
|
UmbracoModule.RouteAttempt -= UmbracoModuleRouteAttempt;
|
|
|
|
LazyInitializer.EnsureInitialized(ref _tasks, ref _started, ref _locker, () =>
|
|
{
|
|
LogHelper.Debug<Scheduler>(() => "Initializing the scheduler");
|
|
var settings = UmbracoConfig.For.UmbracoSettings();
|
|
|
|
var healthCheckConfig = UmbracoConfig.For.HealthCheck();
|
|
|
|
const int delayMilliseconds = 60000;
|
|
var tasks = new List<IBackgroundTask>
|
|
{
|
|
new KeepAlive(_keepAliveRunner, delayMilliseconds, 300000, e.UmbracoContext.Application),
|
|
new ScheduledPublishing(_publishingRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings),
|
|
new ScheduledTasks(_tasksRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings),
|
|
new LogScrubber(_scrubberRunner, delayMilliseconds, LogScrubber.GetLogScrubbingInterval(settings), e.UmbracoContext.Application, settings),
|
|
};
|
|
|
|
if (healthCheckConfig.NotificationSettings.Enabled)
|
|
{
|
|
// If first run time not set, start with just small delay after application start
|
|
int delayInMilliseconds;
|
|
if (string.IsNullOrEmpty(healthCheckConfig.NotificationSettings.FirstRunTime))
|
|
{
|
|
delayInMilliseconds = delayMilliseconds;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise start at scheduled time
|
|
delayInMilliseconds = DateTime.Now.PeriodicMinutesFrom(healthCheckConfig.NotificationSettings.FirstRunTime) * 60 * 1000;
|
|
if (delayInMilliseconds < delayMilliseconds)
|
|
{
|
|
delayInMilliseconds = delayMilliseconds;
|
|
}
|
|
}
|
|
|
|
var periodInMilliseconds = healthCheckConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000;
|
|
tasks.Add(new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, e.UmbracoContext.Application));
|
|
}
|
|
|
|
// ping/keepalive
|
|
// on all servers
|
|
_keepAliveRunner.TryAdd(tasks[0]);
|
|
|
|
// scheduled publishing/unpublishing
|
|
// install on all, will only run on non-slaves servers
|
|
_publishingRunner.TryAdd(tasks[1]);
|
|
|
|
_tasksRunner.TryAdd(tasks[2]);
|
|
|
|
// log scrubbing
|
|
// install on all, will only run on non-slaves servers
|
|
_scrubberRunner.TryAdd(tasks[3]);
|
|
|
|
if (healthCheckConfig.NotificationSettings.Enabled)
|
|
{
|
|
_healthCheckRunner.TryAdd(tasks[4]);
|
|
}
|
|
|
|
return tasks.ToArray();
|
|
});
|
|
}
|
|
}
|
|
}
|