diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php index e0454fb313a..532f7cf8d81 100644 --- a/lib/classes/task/manager.php +++ b/lib/classes/task/manager.php @@ -1227,6 +1227,13 @@ class manager { $task->set_pid($pid); $record = self::record_from_adhoc_task($task); + + // If this is the first time the task has been started, then set the first starting time. + $firststartingtime = $DB->get_field('task_adhoc', 'firststartingtime', ['id' => $record->id]); + if (is_null($firststartingtime)) { + $record->firststartingtime = $time; + } + $DB->update_record('task_adhoc', $record); self::task_starting($task); @@ -1813,7 +1820,7 @@ class manager { $CFG->task_adhoc_failed_retention : static::ADHOC_TASK_FAILED_RETENTION; $DB->delete_records_select( table: 'task_adhoc', - select: 'attemptsavailable = 0 AND timestarted < :time', + select: 'attemptsavailable = 0 AND firststartingtime < :time', params: ['time' => time() - $difftime], ); } diff --git a/lib/db/install.xml b/lib/db/install.xml index 8e47fea79ab..92f0971aeb2 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -3510,6 +3510,7 @@ + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 98d019333ec..9f429e422ca 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1093,5 +1093,20 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2024022300.02); } + if ($oldversion < 2024030500.01) { + + // Define field firststartingtime to be added to task_adhoc. + $table = new xmldb_table('task_adhoc'); + $field = new xmldb_field('firststartingtime', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'attemptsavailable'); + + // Conditionally launch add field firststartingtime. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2024030500.01); + } + return true; } diff --git a/lib/tests/task/adhoc_task_test.php b/lib/tests/task/adhoc_task_test.php index 2c853c6561a..e5c687bf978 100644 --- a/lib/tests/task/adhoc_task_test.php +++ b/lib/tests/task/adhoc_task_test.php @@ -305,7 +305,7 @@ class adhoc_task_test extends \advanced_testcase { // Update the time of the task2 to be older more than 2 days. $DB->set_field( table: 'task_adhoc', - newfield: 'timestarted', + newfield: 'firststartingtime', newvalue: time() - (DAYSECS * 2) - 10, // Plus 10 seconds to make sure it is older than 2 days. conditions: ['id' => $taskid2], ); @@ -322,7 +322,7 @@ class adhoc_task_test extends \advanced_testcase { // Update the time of the task1 to be older than the cleanup time. $DB->set_field( table: 'task_adhoc', - newfield: 'timestarted', + newfield: 'firststartingtime', newvalue: time() - $CFG->task_adhoc_failed_retention - 10, // Plus 10 seconds to make sure it is older than the retention time. conditions: ['id' => $taskid1], ); @@ -730,6 +730,74 @@ class adhoc_task_test extends \advanced_testcase { $this->assertEquals($user->id, $task->get_userid()); } + /** + * Test adhoc task with the first starting time. + * + * @covers ::queue_adhoc_task + * @covers ::get_next_adhoc_task + * @covers ::adhoc_task_starting + * @covers ::adhoc_task_failed + */ + public function test_adhoc_task_get_first_starting_time(): void { + global $DB; + $this->resetAfterTest(true); + + $now = time(); + + // Create an adhoc task. + $task = new adhoc_test_task(); + // Queue it. + $taskid = manager::queue_adhoc_task(task: $task); + + // Get the firststartingtime value. + $firststartingtime = $DB->get_field( + table: 'task_adhoc', + return: 'firststartingtime', + conditions: ['id' => $taskid], + ); + $this->assertNull($firststartingtime); + + // This will make sure that the task will be started after the $now value. + sleep(3); + + // Get the task from the scheduler. + $task = manager::get_next_adhoc_task(timestart: $now); + // Mark the task as starting. + manager::adhoc_task_starting($task); + // Execute the task. + $task->execute(); + // Mark the task as failed. + manager::adhoc_task_failed(task: $task); + + // Get the firststartingtime value. + $origintimestarted = $DB->get_field( + table: 'task_adhoc', + return: 'firststartingtime', + conditions: ['id' => $taskid], + ); + $this->assertNotNull($origintimestarted); + $this->assertGreaterThan($now, $origintimestarted); + + // Get the task from the scheduler. + $task = manager::get_next_adhoc_task(timestart: $now + 86400); + // Mark the task as starting. + manager::adhoc_task_starting($task); + // Execute the task. + $task->execute(); + // Mark the task as failed. + manager::adhoc_task_failed(task: $task); + + // Get the firststartingtime value. + $firststartingtime = $DB->get_field( + table: 'task_adhoc', + return: 'firststartingtime', + conditions: ['id' => $taskid], + ); + + // The firststartingtime value should not be changed. + $this->assertEquals($origintimestarted, $firststartingtime); + } + /** * Test get_concurrency_limit() method to return 0 by default. * diff --git a/version.php b/version.php index bb54388cb5f..4856adee69e 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2024030500.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2024030500.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.4dev+ (Build: 20240305)'; // Human-friendly version name