How to dynamically reschedule a cron task

All cron tasks are executed inside the same context and with full access to the whole set of tasks to be launched. This has a few implications:

As an example of how to benefit from this way of working, let's see how you would go about rescheduling a cron task dynamically.

Let's suppose that you have a cron script that connects to some external service, collects some information and updates it in coreBOS. This script is set to launch daily at some time, but you know that the connection to the external service may fail and you don't want to wait another full day for the next sync to happen. The logic you want to implement is something like this:

In order to implement the above logic, the first thing that we need is to be able to save the “state” of each execution in persistent storage so we can retrieve the number of unsuccessful connections and also reset the task to it's normal time when we are done.

We can use coreBOS settings service for this saving two variables.

The next thing we need is to understand how we can change the next time to launch for the task. For this, we need to understand how the tasks are executed.

Now, looking at how the markFinished method works, we can see that it adds the frequency to the last start date, so if we change the last start date before the increment is done we can define when we want our script to be launched again. In the case we are doing now we know that the markFinished method will increment the time with 24 hours, so if we want the script to be launched 1 hour from “now” then we have to set the last start time to 25 hours ago.

The code would look something like this:

$connerror = coreBOS_Settings::getSetting('ExternalSyncConnectionError', 0);
$synctime = coreBOS_Settings::getSetting('ExternalSyncTime', '02:40'); // sync daily at 2:40 am
 
// try to connect
 
if (connection error) {
	if ($connerror>=2) { // reschedule to normal time and escalate
		coreBOS_Settings::setSetting('ExternalSyncConnectionError', 0);
		list($hour, $min) = explode(':', $synctime);
		$time=mktime($hour, $min, 0, date('m'), date('d')-1, date('y')); // yesterday at sync time so we add 24hours
		$cronTask->setLastStart($time);
		// send email
	} else { // reschedule in an hour
		coreBOS_Settings::setSetting('ExternalSyncConnectionError', $connerror+1);
		$time=mktime(date('h')+1, 0, 0, date('m'), date('d')-1, date('y')); // yesterday at sync time + 1 hour so we add 24hours
		$cronTask->setLastStart($time);
	}
} else {
	// do sync
	coreBOS_Settings::setSetting('ExternalSyncConnectionError', 0);
	list($hour, $min) = explode(':', $synctime);
	$time=mktime($hour, $min, 0, date('m'), date('d')-1, date('y')); // yesterday at sync time so we add 24hours
	$cronTask->setLastStart($time);
}