Creating custom web farm synchronization tasks

Web farm tasks contain code and synchronization data executed by web farm servers. Create custom web farm tasks if you extended Xperience with functions that work directly with the application’s memory or file storage. For example, if your custom function writes files to the file system and you want these files to be synchronized across all servers in your web farm, you need to write a custom web farm task that handles the synchronization.

You need to have web farms correctly configured and working (have more than one server in the web farm) to implement and test this example.

Registering custom web farm tasks

The following example shows how to create a custom synchronization task that logs information events into the event log of all servers in the web farm environment:

  1. Open your Xperience project in Visual Studio (using the WebApp.sln file).

  2. Create a custom class, for example, CustomWebFarmTask, that inherits from WebFarmTaskBase (available in the CMS.Core namespace).

    • Add the class into a custom Class Library project within the solution.
    • The class represents the web farm task in the system and encapsulates both its custom synchronization data and execution logic.
  3. Implement the following:

    1. ExecuteTask method – contains logic executed on target web farm servers. This method is automatically invoked by target servers when processing the web farm task.

    2. (Optional) Override the virtual ConditionMethod method – contains logic used to evaluate whether the task should be created (when WebFarmHelper.CreateTask is invoked). For example, you may only want to create the task based on the result of a Boolean expression, or the value of a system setting.

      
      
      
       using CMS.Base;
       using CMS.Core;
      
       // Represents the web farm task in the system
       public class CustomWebFarmTask : WebFarmTaskBase
       {
           private readonly IEventLogService eventLog;
      
           // Contains the name of the web farm server that created the task
           public string CreatorName { get; set; }
      
           // Holds arbitrary data for processing on target servers
           public object Data { get; set; }
      
           public CustomWebFarmTask()
           {
               eventLog = Service.Resolve<IEventLogService>();
           }
      
           // Contains custom logic to determine whether a new instance of this task should be created whenever WebFarmHelper.CreateTask is invoked
           public override bool ConditionMethod()
           {
               // TODO: Include custom logic that determines whether the task should be created 
      
               return true;
           }
      
           // Contains logic that is executed when a target server processes the web farm task
           public override void ExecuteTask()
           {
               // Logs a record into the system's event log, with 'Execute' as the event code
               string message = $"Server {SystemContext.ServerName} is processing a task from creator {CreatorName}";
               eventLog.LogInformation("CustomTask", "Execute", message);
      
               // TODO: Include custom logic to be processed by target servers here     
           }
       }
      
      
       
  4. Create a custom module class.

    For execution of initialization code, you only need to register a “code-only” module through the API. You do NOT need to create a new module within the Modules application in the Xperience administration interface.

  5. Override the module’s OnInit method and register the task in the system by calling the WebFarmHelper.RegisterTaskmethod.

    
    
    
     using CMS;
     using CMS.DataEngine;
     using CMS.Helpers;
    
     // Registers the custom module
     [assembly: RegisterModule(typeof(CustomWebFarmTaskModule))]
    
     public class CustomWebFarmTaskModule : Module
     {
         // Registers the module in the system under "CustomWebFarmTasks"
         public CustomWebFarmTaskModule()
             : base("CustomWebFarmTasks")
         {
         }
    
         // Contains initialization code that is executed when the application starts
         protected override void OnInit()
         {
             base.OnInit();
    
             // Registers the custom web farm task into the system under the 'CustomWebFarmTask' type
             WebFarmHelper.RegisterTask<CustomWebFarmTask>();
         }
     }
    
    
     
  6. Deploy the assembly with your custom code to all web farm servers. This includes the separate web application that presents your website (MVC or ASP.NET Core).

Each server in the web farm can now process the registered custom tasks.

Creating custom web farm tasks

To create registered web farm tasks, call the WebFarmHelper.CreateTask method (used to create individual web farm tasks from the registered templates) anywhere in your custom code.

If you need to synchronize binary data, for example CRUD operations on custom files present physically on a server’s file system, use WebFarmHelper.CreateIOTask instead.

  1. Write a custom method that handles the creation of web farm tasks. For example:

    
    
    
     using CMS.Base;
     using CMS.Core;
     using CMS.Helpers;
    
     ...
    
     // Creates a custom web farm synchronization task of the 'CustomWebFarmTask' type
     public void CreateCustomTask()
     {
         // TODO: Logic that requires synchronization
    
         // Creates the custom web farm synchronization task, saving it to the database for processing by other web farm servers
         WebFarmHelper.CreateTask(new CustomWebFarmTask()
         {
             CreatorName = SystemContext.ServerName,
             Data = null
         });
    
         // Logs a record into the event log of the server that created the web farm task
         string message = $"Server {SystemContext.ServerName} finished processing an operation and created a task for other web farms.";
         Service.Resolve<IEventLogService>().LogInformation("CustomTask", "Create", message);    
     }
    
    
     
  2. Call the method in your code whenever an event that requires synchronization across instances occurs.

The system now creates new web farm tasks of the specified type when the method is invoked. It also logs a record into the event log, with Create as the event code. You can see the logged event in the Event log application.