Create an agent

You can create an agent that inherits BaseAgent or RecurringAgent, and you can choose whether or not the agent should scale. Reasons to create a custom agent include:

  • Perform regularly scheduled maintenance within the engine, such as purging expired data from a database that the engine relies on. By default, the Processing Engine includes two agents that perform maintenance tasks.

Note

It is rare that you will need to create a custom agent. It is more likely that you will create a custom processing worker that will be executed by the default TaskAgent.

Create an agent that inherits RecurringAgent

The following sample agent calls a method that cleans up data in a fake storage provider. The storage provider is represented by the ICustomProvider interface. The agent inherits RecurringAgent, which means it will run at regular, configurable intervals.

Create an agent class

To create the agent class:

  • Create a class and copy the following sample agent.

Note

The sample ICustomProvider and CustomProvider classes are included in the same file for convenience.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Sitecore.Framework.Conditions;
using Sitecore.Processing.Engine.Abstractions;
using Sitecore.Processing.Engine.Agents;

namespace Sitecore.Documentation.Examples
{
    /// <summary>
    ///     Provides basic agent functionality and services.
    /// </summary>
    public class SampleCleanupAgent : RecurringAgent
    {
        private readonly ICustomProvider _customProvider;

        /// <summary>
        ///
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="options"></param>
        /// <param name="customProvider"></param>
        protected SampleCleanupAgent(ILogger<IAgent> logger, IConfiguration options, ICustomProvider customProvider) : base(options, logger)
        {
            Condition.Requires(customProvider, nameof(customProvider)).IsNotNull();

            _customProvider = customProvider;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        protected override async Task RecurringExecuteAsync(CancellationToken token)
        {
            // Checks if cancellation has been requested in case task is long-running
            // It is your responsibility to check the status of the cancellation token
            while (!token.IsCancellationRequested)
            {
                await _customProvider.CleanData().ConfigureAwait(false);
            }
        }
    }

    /// <summary>
    ///
    /// </summary>
    public interface ICustomProvider {
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        Task GetData();
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        Task CleanData();
    }

    /// <summary>
    ///
    /// </summary>
    public class CustomProvider : ICustomProvider
    {
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public async Task CleanData()
        {
            // Clean up data in custom data provider
            await Task.Delay(1).ConfigureAwait(false);
        }

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public async Task GetData()
        {
            // Get data from custom data provider
            await Task.Delay(1).ConfigureAwait(false);
        }
    }
}

Register agent and services in configuration

  1. Create a file named sc.Processing.Engine.CustomAgents.xml in <engine-root>\\App_Data\\Config\\Global.

  2. Register SampleCleanupAgent and ICustomProvider as shown. This example uses simple configuration to register a single agent.

    <Settings>
        <Sitecore>
            <Processing>
            <Services>
                <ICustomProvider>
                    <Type>Sitecore.Documentation.Examples.CustomProvider, Sitecore.Documentation.Examples</Type>
                    <As>Sitecore.Documentation.Examples.ICustomProvider, Sitecore.Documentation.Examples</As>
                    <LifeTime>Transient</LifeTime>
                </ICustomProvider>
                <SampleCleanupAgent>
                    <Type>Sitecore.Documentation.Examples.SampleCleanupAgent, Sitecore.Documentation.Examples</Type>
                    <As>Sitecore.Processing.Engine.Abstractions.IAgent, Sitecore.Processing.Engine.Abstractions</As>
                    <LifeTime>Transient</LifeTime>
                    <Options>
                        <!-- The period which the agent sleeps before running again. -->
                        <SleepPeriod>0.00:00:14.000</SleepPeriod>
                    </Options>
                </SampleCleanupAgent>
            </Services>
            </Processing>
        </Sitecore>
    </Settings>

Alternatively, if the agent needs to scale, use ParallelAgentsConfiguration to register it:

    <Settings>
        <Sitecore>
            <Processing>
            <Services>
                <ICustomProvider>
                    <Type>Sitecore.Documentation.Examples.CustomProvider, Sitecore.Documentation.Examples</Type>
                    <As>Sitecore.Documentation.Examples.ICustomProvider, Sitecore.Documentation.Examples</As>
                    <LifeTime>Transient</LifeTime>
                </ICustomProvider>
                <SampleCleanupAgent>
                    <Type>Sitecore.Processing.Engine.Agents.ParallelAgentsConfiguration, Sitecore.Processing.Engine</Type>
                    <As>Sitecore.XConnect.DependencyInjection.Abstractions.IXConnectServicesConfiguration, Sitecore.XConnect.DependencyInjection</As>
                    <LifeTime>Transient</LifeTime>
                    <Options>
                        <AgentFixedCount>0</AgentFixedCount>
                        <AgentCoreRatio>0.75</AgentCoreRatio>
                        <AgentConfiguration>
                            <Type>Sitecore.Documentation.Examples.SampleCleanupAgent, Sitecore.Documentation.Examples</Type>
                            <As>Sitecore.Processing.Engine.Abstractions.IAgent, Sitecore.Processing.Engine.Abstractions</As>
                            <LifeTime>Transient</LifeTime>
                            <Options>
                                <SleepPeriod>0.00:00:14.000</SleepPeriod>
                            </Options>
                        </AgentConfiguration>
                    </Options>
                </SampleCleanupAgent>
            </Services>
            </Processing>
        </Sitecore>
    </Settings>

Create an agent that inherits BaseAgent

The following sample agent writes a message to the log on startup and waits 1 millisecond. The agent does not inherit RecurringAgent and will not run at regular intervals.

Important

This particular agent runs once on engine startup. However, your agent might sleep until a particular event occurs, then sleep again until the event happens again. The agent does technically 'recur', but not at regularly scheduled intervals.

Create an agent class

To create an agent class:

  • Create a class and copy the following sample agent.

    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    using Sitecore.Processing.Engine.Abstractions;
    using Sitecore.Processing.Engine.Agents;
    
    namespace Sitecore.Documentation.Examples
    {
        /// <summary>
        ///     Provides basic agent functionality and services.
        /// </summary>
        public class SampleLogAgent : BaseAgent
        {
            /// <summary>
            ///
            /// </summary>
            /// <param name="logger"></param>
            /// <param name="options"></param>
            protected SampleLogAgent(ILogger<IAgent> logger, IConfiguration options) : base(logger, options)
            {
            }
    
            /// <summary>
            ///
            /// </summary>
            /// <param name="token"></param>
            /// <returns></returns>
            public override async Task ExecuteAsync(CancellationToken token)
            {
                    // Write a custom log message
                    //  No cancellation token check in this example as task is unlikely to be long-running
                    base.Log.LogInformation("Your custom agent has started.");
                    await Task.Delay(1).ConfigureAwait(false);
            }
        }
    }

Register agent in configuration

  1. Create a file named sc.Processing.Engine.CustomAgents.xml in <engine-root>\\App_Data\\Config\\Global.

  2. Register SampleCleanupAgent as shown. This example uses simple configuration to register a single agent.

        <Settings>
            <Sitecore>
                <Processing>
                <Services>
                    <SampleLogAgent>
                        <Type>Sitecore.Documentation.Examples.SampleLogAgent, Sitecore.Documentation.Examples</Type>
                        <As>Sitecore.Processing.Engine.Abstractions.IAgent, Sitecore.Processing.Engine.Abstractions</As>
                        <LifeTime>Transient</LifeTime>
                    </SampleLogAgent>
                </Services>
                </Processing>
            </Sitecore>
        </Settings>

Task cancellation

All If you implement an agent that may result in a long-running task, make sure that you check token.IsCancellationRequested property in the ExecuteAsync method (for agents inheriting BaseAgent) or the RecurringExecuteAsync method (agents inheriting RecurringAgent).