6

I have a synchronous scheduled task that has to run everyday at 1:00 AM. But its last run time keeps increasing. How to fix this.

For the "Schedule" field, the value is 20170419|20200422|127|23:59:59
I have a custom code to fire for the OnItemSaving event, so as to always have the Last Run time as 1:00 AM

When the task runs for the first time, the last run field correctly gets updated to current date 1:00AM, but the next day I check, the last run is like 1:08, then 1:10....and it keeps on increasing.

config:

<events>
 <event name="item:saving">
  <handler type="MySite.XdbToJson, MySite" method="OnItemSaving">
  </handler>
 </event>
</events>

Code:

public void GetJsonData()
{
  try
  {
    //this is the code that will execute when the scheduler is run
  }
  catch(Exception)
  {
  }
  finally
  {
     Item scheduledTaskItem = GetItemFromMasterDB("{id of the scheduled task item}");
     UpdateLastRunTime(scheduledTaskItem.ID);
  }
}

private void UpdateLastRunTime(ID scheduledTaskID)
{
  string isoLastRunTimeToSet = GetToBeSetLastRunIsoTime();
  UpdateFieldValue(scheduledTaskID, new ID("{idOfLastRunFieldOfTask}"), isoLastRunTimeToSet);
}

private void UpdateFieldValue(ID itemID, ID fieldID, string fieldValue)
{
  Database db = Configuration.Factory.GetDatabase("master");
  Item item = db.GetItem(itemID, Context.Language, Version.Latest);

  using (new SecurityDisabler())
  {
    item.Editing.BeginEdit();

    using (new EditContext(item))
    {
      item.Fields[fieldID].Value = fieldValue;
    }

    item.Editing.EndEdit();
    item.Editing.AcceptChanges();
  }
 }

private string GetToBeSetLastRunIsoTime()
{
  string isoLastRunTimeToSet = string.Empty;
  string lastRunTimeToSet = "01:00:00";
  var parseDateString = string.Format("{0}/{1}/{2} {3}", DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Year, lastRunTimeToSet);
  System.DateTime lastRunDateTimeToSet;

  if (DateTime.TryParse(parseDateString, out lastRunDateTimeToSet))
  {
    isoLastRunTimeToSet = DateUtil.ToIsoDate(lastRunDateTimeToSet, false, true); 
  }

  return isoLastRunTimeToSet;
}

public void OnItemSaving(object sender, EventArgs args)
{
    Item scheduledTaskItem = Event.ExtractParameter(args, 0) as Item;

    if (scheduledTaskItem.ID == new ID("{id of scheduled task}"))
    {
       string lastRunIsoDateTime = scheduledTaskItem.Fields["Last Run"].Value;

        /*This condition will check if the last run time is as reqd. If not, it will proceed.
         * If the last run field is not empty and also equal to the reqd. time, it means that the Json get data functions
         * were executed and the last run time got updated. No need to continue in this case.
         */
        if (!string.IsNullOrEmpty(lastRunIsoDateTime) && lastRunIsoDateTime != GetToBeSetLastRunIsoTime())
        {
           //check if the task is synchronous
           if (scheduledTaskItem.Fields[Utility.CommonReferences.Templates.Schedule.Fields.Async].Value != "1")
           {
              using (new EventDisabler())
              {
                 UpdateLastRunTime(scheduledTaskItem.ID);
               }
            }
         }
      }         
}
8

It's not possible to run at exactly the same time but it’s possible to get it close to the same time every day.

Scheduled tasks are run in sequence by the Sitecore scheduler. The scheduler checks within a certain interval (defined in the web.config in the /scheduling/frequency and /scheduling/agent settings) for tasks to be run. If a task is over due, it is run, and the time where the task finished is recorded as the next checkpoint.

It is not possible to define a certain time a day the task needs to run. It’s only possible to determine which days a task needs to run, and the interval.

So how do you make a task run once a day, at a certain time?

Well, instead of configuring the task to run every 23:59:59, I make my task run every minute, but only executing the functionality once a day. Inside the task I check the time, and only if the time is inside a certain interval I execute the functionality.

Here is how to do it:

1) Create your task and make it run every 1 minute or 5 minutes (or at least twice as often as your interval).

2) Define an interval where the task is allowed to run. For example at night between 01:00 am and 02:00 am.

3) Build your task in the following manner:

public class TaskRunningOnceAday
{
  public void Execute(Item[] itemArray, CommandItem commandItem, ScheduleItem scheduleItem)
  {
    if (!IsDue(scheduleItem))
      return;

    // EXECUTE MY FUNCTIONALITY
  }

  /// <summary>
  /// Determines whether the specified schedule item is due to run.
  /// </summary>
  /// <remarks>
  /// The scheduled item will only run between defined hours (usually at night) to ensure that the
  /// task is run once a day
  /// Make sure you configure the task to run at least double so often than the time span.
  /// </remarks>
  private bool IsDue(ScheduleItem scheduleItem)
  {
    DateTime time;
    DateTime time2;

    DateTime.TryParse("01:00:00", out time);
    DateTime.TryParse("02:00:00", out time2);

    return (CheckTime(DateTime.Now, time, time2) && !CheckTime(scheduleItem.LastRun, time, time2));
  }

  private bool CheckTime(DateTime time, DateTime after, DateTime before)
  {
    return ((time >= after) && (time <= before));
  }

}

The scheduleItem.LastRun property contains the date and time from where the task was last run.

The function “IsDue” checks to see if the task has run within the selected interval. If not, it returns true and the task may execute it’s functionality. If it has already run, it returns false, and the functionality is skipped.

Credits to https://briancaos.wordpress.com/2011/06/28/run-sitecore-scheduled-task-at-the-same-time-every-day/

| improve this answer | |
  • I was exclusively setting the last run time to 1:00 am using the OnItemSaving event, but it's never so. The last run time keeps increasing everyday. I was under the impression that setting the last run time fixed, will also trigger the task at a fixed time...but looks like it isn't so...correct? But anyways, any idea, why the last run isn't being set to 1:00 am – Qwerty Jul 26 '17 at 13:22
  • And also,...if I set the Schedule field's value as 20170419|20200422|127|00:00:05, i.e to run for every 5 mins. , do I still need to change the setting in web.config. (which is 10 min by default). If yes, then I'm a lil confused now, as what these two time settings are for.... – Qwerty Jul 26 '17 at 13:30
  • have a look here: community.sitecore.net/technical_blogs/b/sitecorejohn_blog/… and YES you need to modify config file – Vlad Iobagiu Jul 26 '17 at 13:36
  • <frequency> element value needs to be smaller than the smallest agent or task interval value configured in Sitecore. – Gabbar Jul 27 '17 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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