I'm getting some funny results from function_task::fetch_next_run(). Under some circumstances it's possible it returns a next run date that is already past.
Based on this task:
Array
(
[tid] => 4
[title] => Weekly Backup
[description] => Automatically backups your MyBB tables to your backups directory.
[file] => backupdb
[minute] => 0
[hour] => 0
[day] => *
[month] => *
[weekday] => 1
[nextrun] => 1234134000
[lastrun] => 0
[enabled] => 1
[logging] => 1
[locked] => 0
)
I called fetch_next_run($task) for the current time (Tue, 03 Feb 2009 17:42:04 +0100).
The current_ and next_ variables inside the function look as follows:
Array
(
[current_minute] => 42
[current_hour] => 17
[current_day] => 03
[current_weekday] => 2
[current_month] => 02
[current_year] => 2009
[next_minute] => 0
[next_hour] => 0
[next_day] => 9
[next_weekday] => 1
[next_month] => 02
[next_year] => 2009
)
So at this time it would run the task next at Mon, 09 Feb 2009 00:00:00 +0100. No problem.
Suppose the task runs on 09 Feb 2009 00:30 i.e. half hour late because there was no visitor earlier, this is what happens:
Array
(
[current_minute] => 30
[current_hour] => 00
[current_day] => 09
[current_weekday] => 1
[current_month] => 02
[current_year] => 2009
[next_minute] => 0
[next_hour] => 0
[next_day] => 9
[next_weekday] => 1
[next_month] => 02
[next_year] => 2009
)
On Mon, 09 Feb 2009 00:30:00 +0100 it schedules the task to be run next on Mon, 09 Feb 2009 00:00:00 +0100 i.e. half an hour in the past?
A task timing out should not cause the task to be run every time, as the nextrun is the first thing that gets updated, before the task itself is even run, to prevent just this from happening.
Is this code taken from somewhere or written from scratch? Scheduling logic is really hard to get right. Hard to verify that it gives the correct results for all cases too. Do you have a testsuite for this kind of thing?
Or is it supposed to work this way, i.e. by saving the last run timestamp and only run it when fetch next run returns something newer than the already saved last run? So many possibilities...
But then I don't see the point of this code?
// Update the nextrun time now, so if the task causes a fatal error, it doesn't get stuck first in the queue
$nextrun = fetch_next_run($task);
$db->update_query("tasks", array("nextrun" => $nextrun), "tid='{$task['tid']}'");
If the task causes a fatal error (or times out) the update doesn't change anything, it sets nextrun to the same value always so its run and run again.