3

I have a custom agent that imports content from an external server. This process can take from 5 minutes to 2 hours. Agent can be started by scheduler or user. I want to prevent two same agents from running at the same time. Currently I have a flag in the DB that determines agent status. I set it to 1 when agent starts and to 0 just before agent stops. At the beginning of agent run I check flag and if it is 0 then agent starts.

It happens that there is an undefined event during import when agent stops and setting flag to 0 doesn't happen. As a result scheduler or user can't start next agent, because flag remains 1.

Is there a better way to monitor if agent is currently running? Any system variable or method?

Code:

public class ImportAgent
{
    public void run()
    {
        if(agentRunning == 0)
        {
            //1. Setting agentRunning to 1

            try
            {
                //2. Importing content
            }
            catch(Exception e)
            {
                //Error
            }
            finally
            {
                //3. Setting agentRunning to 0
            }
        }
        else
        {
            //Agent is running. Waiting till next agent run
        }
    }
}

Config:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <scheduling>
            <agent type="Name.Name.ImportAgent" method="Run" interval="00:30:00"></agent>
        </scheduling>
    </sitecore>
</configuration>
1
  • 1
    Have you tried creating a lazy singleton class instead of writing into the database ? Commented Mar 20 at 15:11

3 Answers 3

3

You can programmatically check if a custom agent is running by using the Sitecore API.

using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Diagnostics;
using Sitecore.Jobs;
using Sitecore.Tasks;

public class CustomAgentHelper
{
    public bool IsCustomAgentRunning(string agentName)
    {
        // Get the scheduler from the Sitecore configuration
        ScheduleItem schedule = Sitecore.Configuration.Factory.GetConfigNode("/scheduling/factories/schedule") as ScheduleItem;
        Assert.IsNotNull(schedule, "Scheduler is not initialized.");

        // Get the agent from the scheduler
        JobItem job = schedule.GetJob(agentName);
        if (job == null)
        {
            // Agent not found
            Log.Warn($"Custom agent '{agentName}' not found.", this);
            return false;
        }

        // Check if the job is currently running
        JobStatus status = JobManager.GetJob(job.JobID)?.Status ?? JobStatus.Initializing;
        bool isRunning = status == JobStatus.Running || status == JobStatus.Queued || status == JobStatus.Initializing;
        return isRunning;
    }
}

You can use this method as follows:

string customAgentName = "YourCustomAgentName";
bool isRunning = IsCustomAgentRunning(customAgentName);
if (isRunning)
{
    Console.WriteLine("Custom agent is running.");
}
else
{
    Console.WriteLine("Custom agent is not running.");
}
2

You can refer to following code snippet to check if the agent is running.

DefaultJobStatus jobStatus = (DefaultJobStatus)JobManager.GetJob("{{agent_name}}")?.Status;
if (jobStatus != null && jobStatus.State != JobState.Running && jobStatus.State != JobState.Queued)

}

You can replace the agent name in the function with the name of your custom agent.

Hope this helps!

1

You can utilize a file lock or a database lock to achieve this. Here's how you can implement it:

using System;
using System.Threading;

public class ImportAgent
{
    private static bool isAgentRunning = false;
    private static readonly object lockObject = new object();

    public void Run()
    {
        if (IsAgentRunning())
        {
            Console.WriteLine("Agent is already running. Aborting execution.");
            return;
        }

        lock (lockObject)
        {
            isAgentRunning = true;
        }

        try
        {
            ImportContent();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error during content import: {ex.Message}");
        }
        finally
        {
            lock (lockObject)
            {
                isAgentRunning = false;
            }
        }
    }

    private bool IsAgentRunning()
    {
        lock (lockObject)
        {
            return isAgentRunning;
        }
    }

    private void ImportContent()
    {
        Console.WriteLine("Importing content...");
        Thread.Sleep(5000);
        Console.WriteLine("Content import completed.");
    }

    public static void Main(string[] args)
    {
        ImportAgent agent = new ImportAgent();
        agent.Run();
    }
}

The lockObject is used to synchronize access to the flag or lock. The CheckIfAgentIsRunning method checks whether the agent is already running, and the SetAgentRunningFlag method sets or releases the flag or lock accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.