EPiServer: working with Scheduled Jobs programmatically

EPiServer provides Scheduled Jobs to run background tasks on schedule. By default those have simple scheduling available, but sometimes you might need more advanced scheduling techniques. EPiServer provides API for that.

In older versions EPiServer had used ScheduledJob class as active record to manipulate Scheduled Jobs, but now all active record methods became obsolete. New way of working with Scheduled Jobs is using ScheduledJobRepository. It provides several methods to get and store Scheduled Jobs which might be useful:

  • Get(Guid id):ScheduledJob - retrieve Scheduled Job by it's ID,
  • Get(string method, string typeName, string assemblyName):ScheduledJob - retrieve Scheduled Job by method name (the name of the method called to when executing it - default name is Execute), type name, assembly name,
  • List():IEnumerable - retrieve all stored Scheduled Jobs,
  • Save(ScheduledJob job):void - store ScheduledJob.

NOTE: When working with List method, I noticed that newly added scheduled jobs might not be returned by it. When job is saved manually through UI then it is returned by List method.

I was missing one method to get existing Scheduled Job by Type. Usually there might be only one job with particular type so it is safe to do that. I created extension method with same name as instance methods - Get.

public static class ScheduledJobRepositoryExtensions
{
    public static ScheduledJob Get(this ScheduledJobRepository repository, Type jobType)
    {
        return repository.List().Single(x => x.TypeName == jobType.FullName);
    }
}

ScheduledJob class has several properties which might be useful to create custom scheduling logic.

  • IntervalType - the type of the interval which might have values:
    • ScheduledIntervalType.Days
    • ScheduledIntervalType.Hours
    • ScheduledIntervalType.Minutes
    • ScheduledIntervalType.Months
    • ScheduledIntervalType.None
    • ScheduledIntervalType.Seconds
    • ScheduledIntervalType.Weeks
    • ScheduledIntervalType.Years
  • IntervalLength - the length of the interval in units defined by IntervalType
  • IsEnabled - property to get or set if job is active

Read-only properties to get job status and if it can be stopped might be useful too.

  • IsStoppable - property if job can be stopped
  • IsRunning - property if job currently is running

And to take some action there are two methods.

  • Stop() - to stop the job if it is stoppable - IsStoppable property is true
  • ExecuteManually() - to run job programmatically by skipping scheduling (I would better schedule it anyway).

And here are few examples how it can be used. In both examples I am using Injected class to get ScheduledJobRepository instance injected in the property (Scheduled Jobs do not support constructor injection). In first example I am using my extension method to get Scheduled Job by it's type. First example schedules another Scheduled Job to run after 10 seconds and second example schedules itself to run after 10 seconds. In second example I am getting Scheduled Job by it's ID which is instance's property - ScheduledJobId.

[ScheduledPlugIn(DisplayName = "I shedule other job", SortIndex = 1000)]
public class OtherJobScheduling : JobBase
{
    public Injected<ScheduledJobRepository> ScheduledJobRepository { get; set; }

    public override string Execute()
    {
        var repository = ScheduledJobRepository.Service;
        var job = repository.Get(typeof(SelfScheduling));
        job.IsEnabled = true;
        job.NextExecution = DateTime.Now.AddSeconds(10);
        repository.Save(job);

        return "Scheduling completed.";
    }
}

[ScheduledPlugIn(DisplayName = "I shedule myself", SortIndex = 1010)]
public class SelfScheduling : JobBase
{
    public Injected<ScheduledJobRepository> ScheduledJobRepository { get; set; }

    public override string Execute()
    {
        var repository = ScheduledJobRepository.Service;
        var job = repository.Get(ScheduledJobId);
        job.IsEnabled = true;
        job.NextExecution = DateTime.Now.AddSeconds(10);
        repository.Save(job);

        return "Scheduling completed.";
    }
}

Working with Scheduled Jobs programmatically is simple while not well documented. Hope that this post will be good reference.

Documentation about how to create Scheduled Jobs can be found on EPiServer World.