MDL-46904 core_task: Gracefully handle rubbish entries in the tasks table.

This commit is contained in:
Damyon Wiese 2014-08-20 13:51:59 +08:00
parent e1eb180806
commit a0ac406055
2 changed files with 58 additions and 5 deletions

View file

@ -66,9 +66,12 @@ class manager {
foreach ($tasks as $task) { foreach ($tasks as $task) {
$record = (object) $task; $record = (object) $task;
$scheduledtask = self::scheduled_task_from_record($record); $scheduledtask = self::scheduled_task_from_record($record);
// Safety check in case the task in the DB does not match a real class (maybe something was uninstalled).
if ($scheduledtask) {
$scheduledtask->set_component($componentname); $scheduledtask->set_component($componentname);
$scheduledtasks[] = $scheduledtask; $scheduledtasks[] = $scheduledtask;
} }
}
return $scheduledtasks; return $scheduledtasks;
} }
@ -237,6 +240,7 @@ class manager {
$classname = '\\' . $classname; $classname = '\\' . $classname;
} }
if (!class_exists($classname)) { if (!class_exists($classname)) {
debugging("Failed to load task: " . $classname, DEBUG_DEVELOPER);
return false; return false;
} }
$task = new $classname; $task = new $classname;
@ -272,6 +276,7 @@ class manager {
$classname = '\\' . $classname; $classname = '\\' . $classname;
} }
if (!class_exists($classname)) { if (!class_exists($classname)) {
debugging("Failed to load task: " . $classname, DEBUG_DEVELOPER);
return false; return false;
} }
/** @var \core\task\scheduled_task $task */ /** @var \core\task\scheduled_task $task */
@ -328,8 +333,11 @@ class manager {
$records = $DB->get_records('task_scheduled', array('componentname' => $componentname), 'classname', '*', IGNORE_MISSING); $records = $DB->get_records('task_scheduled', array('componentname' => $componentname), 'classname', '*', IGNORE_MISSING);
foreach ($records as $record) { foreach ($records as $record) {
$task = self::scheduled_task_from_record($record); $task = self::scheduled_task_from_record($record);
// Safety check in case the task in the DB does not match a real class (maybe something was uninstalled).
if ($task) {
$tasks[] = $task; $tasks[] = $task;
} }
}
return $tasks; return $tasks;
} }
@ -362,8 +370,12 @@ class manager {
*/ */
public static function get_default_scheduled_task($classname) { public static function get_default_scheduled_task($classname) {
$task = self::get_scheduled_task($classname); $task = self::get_scheduled_task($classname);
$componenttasks = array();
// Safety check in case no task was found for the given classname.
if ($task) {
$componenttasks = self::load_default_scheduled_tasks_for_component($task->get_component()); $componenttasks = self::load_default_scheduled_tasks_for_component($task->get_component());
}
foreach ($componenttasks as $componenttask) { foreach ($componenttasks as $componenttask) {
if (get_class($componenttask) == get_class($task)) { if (get_class($componenttask) == get_class($task)) {
@ -387,8 +399,11 @@ class manager {
foreach ($records as $record) { foreach ($records as $record) {
$task = self::scheduled_task_from_record($record); $task = self::scheduled_task_from_record($record);
// Safety check in case the task in the DB does not match a real class (maybe something was uninstalled).
if ($task) {
$tasks[] = $task; $tasks[] = $task;
} }
}
return $tasks; return $tasks;
} }
@ -418,6 +433,11 @@ class manager {
if ($lock = $cronlockfactory->get_lock('adhoc_' . $record->id, 10)) { if ($lock = $cronlockfactory->get_lock('adhoc_' . $record->id, 10)) {
$classname = '\\' . $record->classname; $classname = '\\' . $record->classname;
$task = self::adhoc_task_from_record($record); $task = self::adhoc_task_from_record($record);
// Safety check in case the task in the DB does not match a real class (maybe something was uninstalled).
if (!$task) {
$lock->release();
continue;
}
$task->set_lock($lock); $task->set_lock($lock);
if (!$task->is_blocking()) { if (!$task->is_blocking()) {
@ -463,6 +483,11 @@ class manager {
if ($lock = $cronlockfactory->get_lock(($record->classname), 10)) { if ($lock = $cronlockfactory->get_lock(($record->classname), 10)) {
$classname = '\\' . $record->classname; $classname = '\\' . $record->classname;
$task = self::scheduled_task_from_record($record); $task = self::scheduled_task_from_record($record);
// Safety check in case the task in the DB does not match a real class (maybe something was uninstalled).
if (!$task) {
$lock->release();
continue;
}
$task->set_lock($lock); $task->set_lock($lock);

View file

@ -214,4 +214,32 @@ class core_scheduled_task_testcase extends advanced_testcase {
$task = \core\task\manager::get_next_scheduled_task($now); $task = \core\task\manager::get_next_scheduled_task($now);
$this->assertNull($task); $this->assertNull($task);
} }
public function test_get_broken_scheduled_task() {
global $DB;
$this->resetAfterTest(true);
// Delete all existing scheduled tasks.
$DB->delete_records('task_scheduled');
// Add a scheduled task.
// A broken task that runs all the time.
$record = new stdClass();
$record->blocking = true;
$record->minute = '*';
$record->hour = '*';
$record->dayofweek = '*';
$record->day = '*';
$record->month = '*';
$record->component = 'test_scheduled_task';
$record->classname = '\core\task\scheduled_test_task_broken';
$DB->insert_record('task_scheduled', $record);
$now = time();
// Should not get any task.
$task = \core\task\manager::get_next_scheduled_task($now);
$this->assertDebuggingCalled();
$this->assertNull($task);
}
} }