MDL-81780 tool_task : Adhoc task improvements

Added fail delay column in the adhock task table on the admin page,
Added a new column for a delete action for the adhoc tasks on and
Wrote delete_adhoctask.php for delete functionality of adhoc tasks.
Wrote behat test for the delete functionality. Also there was a
logical error in the previous code where it was checking if the task
is due or not and it was just showing Never or ASAP instead of
actual time so fixed that as well.
This commit is contained in:
waleedhassan
2025-01-16 12:16:04 +00:00
parent f4f166695c
commit c0572a0423
7 changed files with 150 additions and 15 deletions
+3 -2
View File
@@ -28,6 +28,7 @@ require_once($CFG->libdir.'/adminlib.php');
admin_externalpage_setup('adhoctasks');
$failedonly = optional_param('failedonly', false, PARAM_BOOL);
$dueonly = optional_param('dueonly', false, PARAM_BOOL);
$classname = optional_param('classname', null, PARAM_RAW);
$renderer = $PAGE->get_renderer('tool_task');
@@ -37,7 +38,7 @@ if ($classname) {
$PAGE->navbar->add(get_string('adhoctasks', 'tool_task'), $pageurl);
$PAGE->navbar->add(s($classname), $PAGE->url);
$tasks = core\task\manager::get_adhoc_tasks($classname, $failedonly);
$tasks = core\task\manager::get_adhoc_tasks($classname, $failedonly, dueonly: $dueonly);
echo $OUTPUT->header();
@@ -45,7 +46,7 @@ if ($classname) {
echo $renderer->cron_disabled();
}
echo $renderer->adhoc_tasks_class_table($classname, $tasks, ['failedonly' => $failedonly]);
echo $renderer->adhoc_tasks_class_table($classname, $tasks, ['failedonly' => $failedonly , 'dueonly' => $dueonly ]);
} else {
$summary = core\task\manager::get_adhoc_tasks_summary();
+46
View File
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Script deletes an adhoc task.
*
* @package tool_task
* @copyright Catalyst
* @author Waleed ul hassan
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_OUTPUT_BUFFERING', true);
require('../../../config.php');
// Basic security checks.
require_admin();
$context = context_system::instance();
// Get task and check the parameter is valid.
$taskid = required_param('taskid', PARAM_INT);
$task = \core\task\manager::get_adhoc_task($taskid);
if (!$task) {
throw new \moodle_exception('cannotfindinfo', 'error', $taskid);
}
$returnurl = new moodle_url('/admin/tool/task/adhoctasks.php',
['classname' => get_class($task)]);
require_sesskey();
\core\task\manager::delete_adhoc_task($taskid);
redirect($returnurl);
+5
View File
@@ -46,11 +46,13 @@ $string['checklongrunningtasks'] = 'Long running tasks';
$string['checklongrunningtaskcount'] = 'Long running tasks: {$a}';
$string['clearfaildelay_confirm'] = 'Are you sure you want to clear the fail delay for task \'{$a}\'? After clearing the delay, the task will run according to its normal schedule.';
$string['component'] = 'Component';
$string['confirmdeletetaskwithid'] = 'Are you sure you want to delete the task with id: {$a->id}?';
$string['corecomponent'] = 'Core';
$string['crondisabled'] = 'Cron is disabled. No new tasks will be started. The system will not operate properly until it is enabled again.';
$string['cronok'] = 'Cron is running frequently';
$string['default'] = 'Default';
$string['defaultx'] = 'Default: {$a}';
$string['deletetask'] = 'Delete task';
$string['disabled'] = 'Disabled';
$string['disabled_help'] = 'Disabled scheduled tasks are not executed from cron, however they can still be executed manually via the CLI tool.';
$string['edittaskschedule'] = 'Edit task schedule: {$a}';
@@ -85,6 +87,7 @@ $string['runadhoctasks'] = 'Run all \'{$a}\' tasks';
$string['runadhoctasksfailed'] = 'Run failed \'{$a}\' tasks';
$string['runnow_confirm'] = 'Are you sure you want to run this task \'{$a}\' now? The task will run on the web server and may take some time to complete.';
$string['runclassname'] = 'Run all';
$string['runclassnamedueonly'] = 'Run due only';
$string['runclassnamefailedonly'] = 'Run all failed';
$string['runpattern'] = 'Run pattern';
$string['scheduled'] = 'Scheduled';
@@ -140,3 +143,5 @@ $string['taskschedulemonth_help'] = 'Month field for task schedule. The field us
* <strong>1,5</strong> Every January and May';
$string['privacy:metadata'] = 'The Scheduled task configuration plugin does not store any personal data.';
$string['viewlogs'] = 'View logs for {$a}';
$string['actions'] = 'Actions';
$string['deleteadhoctask'] = 'Delete ad hoc task {$a->id}';
+43 -3
View File
@@ -96,6 +96,16 @@ class tool_task_renderer extends plugin_renderer_base {
),
'task-runnow'
);
$duecontent .= html_writer::div(
html_writer::link(
new moodle_url(
$adhocrunurl,
['classname' => $classname, 'dueonly' => 1]
),
get_string('runclassnamedueonly', 'tool_task')
),
'task-runnow'
);
}
// Mark cell if has failed tasks.
@@ -233,6 +243,7 @@ class tool_task_renderer extends plugin_renderer_base {
*/
private function generate_adhoc_tasks_simple_table(array $tasks, bool $wantruntasks = false): html_table {
$adhocrunurl = '/admin/tool/task/run_adhoctasks.php';
$adhocdeleteurl = '/admin/tool/task/delete_adhoctasks.php';
$now = time();
$failedstr = get_string('failed', 'tool_task');
@@ -243,7 +254,9 @@ class tool_task_renderer extends plugin_renderer_base {
get_string('taskid', 'tool_task'),
get_string('nextruntime', 'tool_task'),
get_string('payload', 'tool_task'),
$failedstr
$failedstr,
get_string('faildelay', 'tool_task'),
get_string('actions','tool_task'),
];
$table->attributes['class'] = 'generaltable';
@@ -263,9 +276,9 @@ class tool_task_renderer extends plugin_renderer_base {
// Mark cell if task has failed.
$faildelay = $task->get_fail_delay();
$faildelaycell = new html_table_cell($faildelay ? $failedstr : '');
$failedcell = new html_table_cell($faildelay ? $failedstr : '');
if ($faildelay) {
$faildelaycell->attributes['class'] = 'table-danger';
$failedcell->attributes['class'] = 'table-danger';
}
// Prepares the next run time cell contents.
@@ -293,11 +306,38 @@ class tool_task_renderer extends plugin_renderer_base {
}
}
// Create fail delay cell.
$faildelaycellcontent = $faildelay;
$faildelaycell = new html_table_cell($faildelaycellcontent);
if ($faildelay) {
$faildelaycell->attributes['class'] = 'table-danger';
}
// Add delete link with modal trigger.
$deletelink = html_writer::link(
new moodle_url($adhocdeleteurl, ['taskid' => $taskid, 'sesskey' => sesskey()]),
get_string('delete'),
[
'class' => 'btn btn-danger',
'role' => 'button',
'aria-label' => get_string('deleteadhoctask', 'tool_task', $taskid),
'data-confirmation' => 'modal',
'data-confirmation-type' => 'delete',
'data-confirmation-title-str' => '["deleteadhoctask", "tool_task",{"id":'.$taskid.'}]',
'data-confirmation-content-str' => '["confirmdeletetaskwithid", "tool_task", {"id":'.$taskid.'}]',
'data-confirmation-yes-button-str' => '["delete", "core"]',
]
);
$deletecell = new html_table_cell($deletelink);
$data[] = new html_table_row([
$taskidcell,
new html_table_cell($nextrun),
new html_table_cell($task->get_custom_data_as_string()),
$failedcell,
$faildelaycell,
$deletecell,
]);
}
$table->data = $data;
+10 -7
View File
@@ -37,6 +37,7 @@ $tasksurl = '/admin/tool/task/adhoctasks.php';
// Allow execution of single task. This requires login and has different rules.
$classname = optional_param('classname', null, PARAM_RAW);
$failedonly = optional_param('failedonly', false, PARAM_BOOL);
$dueonly = optional_param('dueonly', false, PARAM_BOOL);
$taskid = optional_param('id', null, PARAM_INT);
$confirmed = optional_param('confirm', 0, PARAM_INT);
@@ -45,7 +46,7 @@ if (!\core\task\manager::is_runnable()) {
throw new moodle_exception('cannotfindthepathtothecli', 'tool_task', $redirecturl->out());
}
$params = ['classname' => $classname, 'failedonly' => $failedonly, 'id' => $taskid];
$params = ['classname' => $classname, 'failedonly' => $failedonly, 'dueonly' => $dueonly, 'id' => $taskid];
// Check input parameter id against all existing tasks.
if ($taskid) {
@@ -69,7 +70,7 @@ if ($taskid) {
$now = time();
$tasks = array_filter(
core\task\manager::get_adhoc_tasks($classname, $failedonly, true),
core\task\manager::get_adhoc_tasks($classname, $failedonly, $dueonly, true),
function ($t) use ($now) {
return $t->get_fail_delay() || $t->get_next_run_time() <= $now;
}
@@ -130,14 +131,16 @@ if ($taskid) {
\core\task\manager::run_adhoc_from_cli($taskid);
echo html_writer::end_tag('pre');
} else {
$repeat = core\task\manager::get_adhoc_tasks($classname, $failedonly, true);
$repeat = core\task\manager::get_adhoc_tasks($classname, $failedonly, $dueonly, true);
// Run failed first (if any). We have to run them separately anyway,
// because faildelay is observed if failed flag is not true.
echo html_writer::tag('p', get_string('runningfailedtasks', 'tool_task'), ['class' => 'lead']);
echo html_writer::start_tag('pre', ['class' => 'task-output']);
\core\task\manager::run_all_adhoc_from_cli(true, $classname);
echo html_writer::end_tag('pre');
if (!$dueonly) {
echo html_writer::tag('p', get_string('runningfailedtasks', 'tool_task'), ['class' => 'lead']);
echo html_writer::start_tag('pre', ['class' => 'task-output']);
\core\task\manager::run_all_adhoc_from_cli(true, $classname);
echo html_writer::end_tag('pre');
}
if (!$failedonly) {
echo html_writer::tag('p', get_string('runningalltasks', 'tool_task'), ['class' => 'lead']);
@@ -0,0 +1,21 @@
@tool @tool_task @javascript
Feature: Delete an adhoc task
In order to manage adhoc tasks
As an admin
I need to be able to delete adhoc tasks
Scenario: Delete an existing adhoc task
Given I log in as "admin"
And the following "tool_task > adhoc tasks" exist:
| classname | seconds | hostname | pid |
| \core\task\asynchronous_backup_task | 7201 | c69335460f7f | 1915 |
| \core\task\asynchronous_restore_task | 172800 | c69335460f7f | 1916 |
And I navigate to "Server > Tasks > Ad hoc tasks" in site administration
Then "asynchronous_backup_task" "table_row" should exist
And "asynchronous_restore_task" "table_row" should exist
And I follow "asynchronous_backup_task"
When I follow "Delete"
And I click on "Delete" "button" in the ".modal-dialog" "css_element"
Then I navigate to "Server > Tasks > Ad hoc tasks" in site administration
And "asynchronous_backup_task" "table_row" should not exist
And "asynchronous_restore_task" "table_row" should exist
+22 -3
View File
@@ -507,11 +507,17 @@ class manager {
* This function load the adhoc tasks for a given classname.
*
* @param string $classname
* @param bool $failedonly
* @param bool $skiprunning do not return tasks that are in the running state
* @param bool $failedonly Return only failed tasks
* @param bool $skiprunning Do not return tasks that are in the running state
* @param bool $dueonly Return only tasks that are due to run (nextruntime < now)
* @return array
*/
public static function get_adhoc_tasks(string $classname, bool $failedonly = false, bool $skiprunning = false): array {
public static function get_adhoc_tasks(
string $classname,
bool $failedonly = false,
bool $skiprunning = false,
bool $dueonly = false
): array {
global $DB;
$conds[] = 'classname = ?';
@@ -519,6 +525,8 @@ class manager {
if ($failedonly) {
$conds[] = 'faildelay > 0';
} else if ($dueonly) {
$conds[] = 'faildelay = 0';
}
if ($skiprunning) {
$conds[] = 'timestarted IS NULL';
@@ -950,6 +958,17 @@ class manager {
return null;
}
/**
* This function will delete an adhoc task by id. The task will be removed
* from the database.
*
* @param int $taskid
*/
public static function delete_adhoc_task(int $taskid): void {
global $DB;
$DB->delete_records('task_adhoc', ['id' => $taskid]);
}
/**
* This function will set locks on the task.
*