From 96e1633f57b2076e33c766759129694ec28f869f Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Wed, 9 Aug 2017 08:04:00 +0800 Subject: [PATCH] MDL-59768 tasks: schedule task only if it is not scheduled --- backup/moodle2/restore_stepslib.php | 2 +- lib/classes/task/manager.php | 26 ++++++++++++++++++++- lib/tests/adhoc_task_test.php | 36 +++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index dfcf545e91c..10872f824f1 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -5560,6 +5560,6 @@ class restore_calendar_action_events extends restore_execution_step { // The task will automatically populate all data. $task = new \core\task\refresh_mod_calendar_events_task(); $task->set_custom_data(array('courseid' => $this->get_courseid())); - \core\task\manager::queue_adhoc_task($task); + \core\task\manager::queue_adhoc_task($task, true); } } diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php index 106878b8bcf..b19b689890d 100644 --- a/lib/classes/task/manager.php +++ b/lib/classes/task/manager.php @@ -125,13 +125,30 @@ class manager { $DB->delete_records_select('task_scheduled', $sql, $params); } + /** + * Checks if the task with the same classname, component and customdata is already scheduled + * + * @param adhoc_task $task + * @return bool + */ + protected static function task_is_scheduled($task) { + global $DB; + $record = self::record_from_adhoc_task($task); + $params = [$record->classname, $record->component, $record->customdata]; + $sql = 'classname = ? AND component = ? AND ' . + $DB->sql_compare_text('customdata', \core_text::strlen($record->customdata) + 1) . ' = ?'; + return $DB->record_exists_select('task_adhoc', $sql, $params); + } + /** * Queue an adhoc task to run in the background. * * @param \core\task\adhoc_task $task - The new adhoc task information to store. + * @param bool $checkforexisting - If set to true and the task with the same classname, component and customdata + * is already scheduled then it will not schedule a new task. Can be used only for ASAP tasks. * @return boolean - True if the config was saved. */ - public static function queue_adhoc_task(adhoc_task $task) { + public static function queue_adhoc_task(adhoc_task $task, $checkforexisting = false) { global $DB; $record = self::record_from_adhoc_task($task); @@ -139,6 +156,13 @@ class manager { if (!$task->get_next_run_time()) { $record->nextruntime = time() - 1; } + + // Check if the same task is already scheduled. + if ($checkforexisting && self::task_is_scheduled($task)) { + return false; + } + + // Queue the task. $result = $DB->insert_record('task_adhoc', $record); return $result; diff --git a/lib/tests/adhoc_task_test.php b/lib/tests/adhoc_task_test.php index d1ec1d88390..e4ebcacc71e 100644 --- a/lib/tests/adhoc_task_test.php +++ b/lib/tests/adhoc_task_test.php @@ -149,4 +149,40 @@ class core_adhoc_task_testcase extends advanced_testcase { $this->assertInstanceOf('\\core\\task\\adhoc_test2_task', $task); } } + + /** + * Test queue_adhoc_task "if not scheduled". + */ + public function test_queue_adhoc_task_if_not_scheduled() { + $this->resetAfterTest(true); + + // Schedule adhoc task. + $task1 = new \core\task\adhoc_test_task(); + $task1->set_custom_data(array('courseid' => 10)); + $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task1, true)); + $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); + + // Schedule same adhoc task with different custom data. + $task2 = new \core\task\adhoc_test_task(); + $task2->set_custom_data(array('courseid' => 1)); + $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task2, true)); + $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); + + // Schedule same adhoc task with same custom data. + $task3 = new \core\task\adhoc_test_task(); + $task3->set_custom_data(array('courseid' => 1)); + $this->assertEmpty(\core\task\manager::queue_adhoc_task($task3, true)); + $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); + + // Schedule same adhoc task without custom data. + $task4 = new \core\task\adhoc_test_task(); + $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task4, true)); + $this->assertEquals(3, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); + + // Schedule same adhoc task without custom data (again). + $task5 = new \core\task\adhoc_test_task(); + $this->assertEmpty(\core\task\manager::queue_adhoc_task($task5, true)); + $this->assertEquals(3, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'))); + + } }