diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php index 5c6bef2d19b..12ea2f93690 100644 --- a/lib/classes/task/manager.php +++ b/lib/classes/task/manager.php @@ -85,53 +85,31 @@ class manager { */ public static function reset_scheduled_tasks_for_component($componentname) { global $DB; - $cronlockfactory = \core\lock\lock_config::get_lock_factory('cron'); - - if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10, 60)) { - throw new \moodle_exception('locktimeout'); - } $tasks = self::load_default_scheduled_tasks_for_component($componentname); - $tasklocks = array(); foreach ($tasks as $taskid => $task) { $classname = get_class($task); if (strpos($classname, '\\') !== 0) { $classname = '\\' . $classname; } - // For tasks, the first run should also follow the schedule. - $task->set_next_run_time($task->get_next_scheduled_time()); - - // If there is an existing task with a custom schedule, do not override it. - $currenttask = self::get_scheduled_task($classname); - if ($currenttask && $currenttask->is_customised()) { - $tasks[$taskid] = $currenttask; - } - - if (!$lock = $cronlockfactory->get_lock($classname, 10, 60)) { - // Could not get all the locks required - release all locks and fail. - foreach ($tasklocks as $tasklock) { - $tasklock->release(); + if ($currenttask = self::get_scheduled_task($classname)) { + if ($currenttask->is_customised()) { + // If there is an existing task with a custom schedule, do not override it. + continue; } - $cronlock->release(); - throw new \moodle_exception('locktimeout'); + + // Update the record from the default task data. + self::configure_scheduled_task($task); + } else { + // Ensure that the first run follows the schedule. + $task->set_next_run_time($task->get_next_scheduled_time()); + + // Insert the new task in the database. + $record = self::record_from_scheduled_task($task); + $DB->insert_record('task_scheduled', $record); } - $tasklocks[] = $lock; } - - // Got a lock on cron and all the tasks for this component, time to reset the config. - $DB->delete_records('task_scheduled', array('component' => $componentname)); - foreach ($tasks as $task) { - $record = self::record_from_scheduled_task($task); - $DB->insert_record('task_scheduled', $record); - } - - // Release the locks. - foreach ($tasklocks as $tasklock) { - $tasklock->release(); - } - - $cronlock->release(); } /** diff --git a/lib/tests/scheduled_task_test.php b/lib/tests/scheduled_task_test.php index e05edd61357..2d5e2058860 100644 --- a/lib/tests/scheduled_task_test.php +++ b/lib/tests/scheduled_task_test.php @@ -177,6 +177,25 @@ class core_scheduled_task_testcase extends advanced_testcase { // We reset this field, because we do not want to compare it. $firsttaskrecord->nextruntime = '0'; + // Delete a task to simulate the fact that its new. + $secondtask = next($defaulttasks); + $DB->delete_records('task_scheduled', array('classname' => '\\' . trim(get_class($secondtask), '\\'))); + $this->assertFalse(\core\task\manager::get_scheduled_task(get_class($secondtask))); + + // Edit a task to simulate a change in its definition (as if it was not customised). + $thirdtask = next($defaulttasks); + $thirdtask->set_minute('1'); + $thirdtask->set_hour('2'); + $thirdtask->set_month('3'); + $thirdtask->set_day_of_week('4'); + $thirdtask->set_day('5'); + $thirdtaskbefore = \core\task\manager::get_scheduled_task(get_class($thirdtask)); + $thirdtaskbefore->set_next_run_time(null); // Ignore this value when comparing. + \core\task\manager::configure_scheduled_task($thirdtask); + $thirdtask = \core\task\manager::get_scheduled_task(get_class($thirdtask)); + $thirdtask->set_next_run_time(null); // Ignore this value when comparing. + $this->assertNotEquals($thirdtaskbefore, $thirdtask); + // Now call reset on all the tasks. \core\task\manager::reset_scheduled_tasks_for_component('moodle'); @@ -192,6 +211,17 @@ class core_scheduled_task_testcase extends advanced_testcase { // Assert a customised task was not altered by reset. $this->assertEquals($firsttaskrecord, $newfirsttaskrecord); + // Assert that the second task was added back. + $secondtaskafter = \core\task\manager::get_scheduled_task(get_class($secondtask)); + $secondtaskafter->set_next_run_time(null); // Do not compare the nextruntime. + $secondtask->set_next_run_time(null); + $this->assertEquals($secondtask, $secondtaskafter); + + // Assert that the third task edits were overridden. + $thirdtaskafter = \core\task\manager::get_scheduled_task(get_class($thirdtask)); + $thirdtaskafter->set_next_run_time(null); + $this->assertEquals($thirdtaskbefore, $thirdtaskafter); + // Assert we have the same number of tasks. $this->assertEquals($initcount, $finalcount); }