2 YEARS AGO

Automatically generate scheduled tasks for web farms

Does your Kentico website automatically scale out? Are you levering Kentico web farms? Did you ensure that certain scheduled tasks are being executed on every server in the farm? If the last answer is no then please continue reading.

Introduction

If you are using more than one web server (e.g. via autoscaling) then you will need to utilize the web farms functionality to ensure synchronization between the servers. Kentico already has a great built in module to handle web farm synchronization which can be easily enabled via settings. With the upcoming version 9 you will gain a lot of time, as web farm support can be easily turned on without additional configuration. Kentico will automatically take care of unexpected failures using it's self-healing capabilities :)

Web farm servers can either be configured manually or generated automatically. Setting them manually means editing the web.config for each server which is far from optimal in a cloud environment, especially in autoscaling scenarios. However there is a catch. When you are using web farms a couple of scheduled tasks need to be configured to execute on every server (typically those that work with the file system). It concerns the following scheduled tasks:

 - Execute search tasks
 - Optimize search indexes
 - Process analytics log
 - Delete image editor history
 - Delete old file system cache files
 - Delete old temporary upload files
 - Delete old temporary attachments
 - Clean unused memory
 
This can be achieved by cloning the scheduled task and setting it's server name to the name of the web farm server. This is a manual step described in the documentation and there is no out-of-the-box functionality to do it automatically when the instance is dynamically scaled.

For more info check out: https://docs.kentico.com/display/K82/Configuring+web+farm+servers

Solution with code sample

One way to solve this is to develop a custom handler that creates scheduled tasks at the Insert.After and Delete.After events of the web farm server object type:

WebFarmServerInfo.TYPEINFO.Events.Insert.After += Insert_After;
WebFarmServerInfo.TYPEINFO.Events.Delete.After += Delete_After;

You can then easily generate the tasks using the following code snippet:

WebFarmServerInfo wfsi = e.Object as WebFarmServerInfo;

// Don't create task if it already exists
if (TaskInfoProvider.GetTasks().WhereEquals("TaskName", wfsi.ServerName + ".Search.TaskExecutor").HasResults())
{
    return;
}

// Set the interval for every hour
var interval = new TaskInterval
{
    Every = 1,
    Period = SchedulingHelper.PERIOD_HOUR,
    StartTime = DateTime.Now,
    BetweenEnd = DateTime.Today.AddMinutes(-1),
    Days = new ArrayList(Enum.GetNames(typeof(DayOfWeek)))
};

// Register the scheduled task
var task = new TaskInfo
{
    TaskAssemblyName = "CMS.Scheduler",
    TaskClass = "CMS.Scheduler.SearchTaskExecutor",
    TaskDisplayName = wfsi.ServerName + " - Execute search tasks",
    TaskInterval = SchedulingHelper.EncodeInterval(interval),
    TaskName = wfsi.ServerName + ".Search.TaskExecutor",
    TaskNextRunTime = DateTime.Now,
    TaskEnabled = true,
    TaskData = String.Empty,
    TaskServerName = wfsi.ServerName
};
TaskInfoProvider.SetTaskInfo(task);

Enjoy!