mirror of
https://github.com/moodle/moodle.git
synced 2025-03-18 22:50:19 +01:00
Merge branch 'MDL-61063-master' of https://github.com/sammarshallou/moodle
This commit is contained in:
commit
d7ba45290b
69
admin/tool/task/clear_fail_delay.php
Normal file
69
admin/tool/task/clear_fail_delay.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?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 clears the fail delay for a task and reschedules its next execution.
|
||||
*
|
||||
* @package tool_task
|
||||
* @copyright 2017 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
require('../../../config.php');
|
||||
|
||||
require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// Basic security checks.
|
||||
require_login();
|
||||
$context = context_system::instance();
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
// Get task and check the parameter is valid.
|
||||
$taskname = required_param('task', PARAM_RAW_TRIMMED);
|
||||
$task = \core\task\manager::get_scheduled_task($taskname);
|
||||
if (!$task) {
|
||||
print_error('cannotfindinfo', 'error', $taskname);
|
||||
}
|
||||
|
||||
// If actually doing the clear, then carry out the task and redirect to the scheduled task page.
|
||||
if (optional_param('confirm', 0, PARAM_INT)) {
|
||||
require_sesskey();
|
||||
|
||||
\core\task\manager::clear_fail_delay($task);
|
||||
|
||||
redirect(new moodle_url('/admin/tool/task/scheduledtasks.php'));
|
||||
}
|
||||
|
||||
// Start output.
|
||||
$PAGE->set_url(new moodle_url('/admin/tool/task/schedule_task.php'));
|
||||
$PAGE->set_context($context);
|
||||
$PAGE->navbar->add(get_string('scheduledtasks', 'tool_task'), new moodle_url('/admin/tool/task/scheduledtasks.php'));
|
||||
$PAGE->navbar->add(s($task->get_name()));
|
||||
$PAGE->navbar->add(get_string('clear'));
|
||||
echo $OUTPUT->header();
|
||||
|
||||
// The initial request just shows the confirmation page; we don't do anything further unless
|
||||
// they confirm.
|
||||
echo $OUTPUT->confirm(get_string('clearfaildelay_confirm', 'tool_task', $task->get_name()),
|
||||
new single_button(new moodle_url('/admin/tool/task/clear_fail_delay.php',
|
||||
array('task' => $taskname, 'confirm' => 1, 'sesskey' => sesskey())),
|
||||
get_string('clear')),
|
||||
new single_button(new moodle_url('/admin/tool/task/scheduledtasks.php'),
|
||||
get_string('cancel'), false));
|
||||
|
||||
echo $OUTPUT->footer();
|
@ -25,6 +25,7 @@
|
||||
$string['asap'] = 'ASAP';
|
||||
$string['backtoscheduledtasks'] = 'Back to scheduled tasks';
|
||||
$string['blocking'] = 'Blocking';
|
||||
$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['corecomponent'] = 'Core';
|
||||
$string['default'] = 'Default';
|
||||
|
@ -112,6 +112,14 @@ class tool_task_renderer extends plugin_renderer_base {
|
||||
get_string('runnow', 'tool_task')), 'task-runnow');
|
||||
}
|
||||
|
||||
$clearfail = '';
|
||||
if ($task->get_fail_delay()) {
|
||||
$clearfail = html_writer::div(html_writer::link(
|
||||
new moodle_url('/admin/tool/task/clear_fail_delay.php',
|
||||
array('task' => get_class($task), 'sesskey' => sesskey())),
|
||||
get_string('clear')), 'task-clearfaildelay');
|
||||
}
|
||||
|
||||
$row = new html_table_row(array(
|
||||
$namecell,
|
||||
$componentcell,
|
||||
@ -123,7 +131,7 @@ class tool_task_renderer extends plugin_renderer_base {
|
||||
new html_table_cell($task->get_day()),
|
||||
new html_table_cell($task->get_day_of_week()),
|
||||
new html_table_cell($task->get_month()),
|
||||
new html_table_cell($task->get_fail_delay()),
|
||||
new html_table_cell($task->get_fail_delay() . $clearfail),
|
||||
new html_table_cell($customised)));
|
||||
|
||||
// Cron-style values must always be LTR.
|
||||
|
@ -10,6 +10,7 @@
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
#page-admin-tool-task-scheduledtasks .task-runnow {
|
||||
#page-admin-tool-task-scheduledtasks .task-runnow,
|
||||
#page-admin-tool-task-scheduledtasks .task-clearfaildelay {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
53
admin/tool/task/tests/behat/behat_tool_task.php
Normal file
53
admin/tool/task/tests/behat/behat_tool_task.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Behat step definitions for scheduled task administration.
|
||||
*
|
||||
* @package tool_task
|
||||
* @copyright 2017 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
|
||||
|
||||
/**
|
||||
* Behat step definitions for scheduled task administration.
|
||||
*
|
||||
* @package tool_task
|
||||
* @copyright 2017 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_tool_task extends behat_base {
|
||||
|
||||
/**
|
||||
* Set a fake fail delay for a scheduled task.
|
||||
*
|
||||
* @Given /^the scheduled task "(?P<task_name>[^"]+)" has a fail delay of "(?P<seconds_number>\d+)" seconds$/
|
||||
* @param string $task Task classname
|
||||
* @param int $seconds Fail delay time in seconds
|
||||
*/
|
||||
public function scheduled_task_has_fail_delay_seconds($task, $seconds) {
|
||||
global $DB;
|
||||
$id = $DB->get_field('task_scheduled', 'id', ['classname' => $task], IGNORE_MISSING);
|
||||
if (!$id) {
|
||||
throw new Exception('Unknown scheduled task: ' . $task);
|
||||
}
|
||||
$DB->set_field('task_scheduled', 'faildelay', $seconds, ['id' => $id]);
|
||||
}
|
||||
}
|
25
admin/tool/task/tests/behat/clear_fail_delay.feature
Normal file
25
admin/tool/task/tests/behat/clear_fail_delay.feature
Normal file
@ -0,0 +1,25 @@
|
||||
@tool @tool_task
|
||||
Feature: Clear scheduled task fail delay
|
||||
In order to stop failures from delaying a scheduled task run
|
||||
As an admin
|
||||
I need to be able to clear the fail delay on a task
|
||||
|
||||
Background:
|
||||
Given the scheduled task "\core\task\send_new_user_passwords_task" has a fail delay of "60" seconds
|
||||
And I log in as "admin"
|
||||
And I navigate to "Scheduled tasks" node in "Site administration > Server"
|
||||
|
||||
Scenario: Clear fail delay
|
||||
When I click on "Clear" "text" in the "Send new user passwords" "table_row"
|
||||
And I should see "Are you sure you want to clear the fail delay"
|
||||
And I press "Clear"
|
||||
|
||||
Then I should not see "60" in the "Send new user passwords" "table_row"
|
||||
And I should not see "Clear" in the "Send new user passwords" "table_row"
|
||||
|
||||
Scenario: Cancel clearing the fail delay
|
||||
When I click on "Clear" "text" in the "Send new user passwords" "table_row"
|
||||
And I press "Cancel"
|
||||
|
||||
Then I should see "60" in the "Send new user passwords" "table_row"
|
||||
And I should see "Clear" in the "Send new user passwords" "table_row"
|
@ -89,10 +89,7 @@ class manager {
|
||||
$validtasks = array();
|
||||
|
||||
foreach ($tasks as $taskid => $task) {
|
||||
$classname = get_class($task);
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($task);
|
||||
|
||||
$validtasks[] = $classname;
|
||||
|
||||
@ -188,10 +185,7 @@ class manager {
|
||||
public static function configure_scheduled_task(scheduled_task $task) {
|
||||
global $DB;
|
||||
|
||||
$classname = get_class($task);
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($task);
|
||||
|
||||
$original = $DB->get_record('task_scheduled', array('classname'=>$classname), 'id', MUST_EXIST);
|
||||
|
||||
@ -211,10 +205,7 @@ class manager {
|
||||
*/
|
||||
public static function record_from_scheduled_task($task) {
|
||||
$record = new \stdClass();
|
||||
$record->classname = get_class($task);
|
||||
if (strpos($record->classname, '\\') !== 0) {
|
||||
$record->classname = '\\' . $record->classname;
|
||||
}
|
||||
$record->classname = self::get_canonical_class_name($task);
|
||||
$record->component = $task->get_component();
|
||||
$record->blocking = $task->is_blocking();
|
||||
$record->customised = $task->is_customised();
|
||||
@ -239,10 +230,7 @@ class manager {
|
||||
*/
|
||||
public static function record_from_adhoc_task($task) {
|
||||
$record = new \stdClass();
|
||||
$record->classname = get_class($task);
|
||||
if (strpos($record->classname, '\\') !== 0) {
|
||||
$record->classname = '\\' . $record->classname;
|
||||
}
|
||||
$record->classname = self::get_canonical_class_name($task);
|
||||
$record->id = $task->get_id();
|
||||
$record->component = $task->get_component();
|
||||
$record->blocking = $task->is_blocking();
|
||||
@ -261,10 +249,7 @@ class manager {
|
||||
* @return \core\task\adhoc_task
|
||||
*/
|
||||
public static function adhoc_task_from_record($record) {
|
||||
$classname = $record->classname;
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($record->classname);
|
||||
if (!class_exists($classname)) {
|
||||
debugging("Failed to load task: " . $classname, DEBUG_DEVELOPER);
|
||||
return false;
|
||||
@ -301,10 +286,7 @@ class manager {
|
||||
* @return \core\task\scheduled_task
|
||||
*/
|
||||
public static function scheduled_task_from_record($record) {
|
||||
$classname = $record->classname;
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($record->classname);
|
||||
if (!class_exists($classname)) {
|
||||
debugging("Failed to load task: " . $classname, DEBUG_DEVELOPER);
|
||||
return false;
|
||||
@ -381,9 +363,7 @@ class manager {
|
||||
public static function get_scheduled_task($classname) {
|
||||
global $DB;
|
||||
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($classname);
|
||||
// We are just reading - so no locks required.
|
||||
$record = $DB->get_record('task_scheduled', array('classname'=>$classname), '*', IGNORE_MISSING);
|
||||
if (!$record) {
|
||||
@ -401,9 +381,7 @@ class manager {
|
||||
public static function get_adhoc_tasks($classname) {
|
||||
global $DB;
|
||||
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($classname);
|
||||
// We are just reading - so no locks required.
|
||||
$records = $DB->get_records('task_adhoc', array('classname' => $classname));
|
||||
|
||||
@ -601,10 +579,7 @@ class manager {
|
||||
$delay = 86400;
|
||||
}
|
||||
|
||||
$classname = get_class($task);
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($task);
|
||||
|
||||
$task->set_next_run_time(time() + $delay);
|
||||
$task->set_fail_delay($delay);
|
||||
@ -657,10 +632,7 @@ class manager {
|
||||
$delay = 86400;
|
||||
}
|
||||
|
||||
$classname = get_class($task);
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($task);
|
||||
|
||||
$record = $DB->get_record('task_scheduled', array('classname' => $classname));
|
||||
$record->nextruntime = time() + $delay;
|
||||
@ -673,6 +645,23 @@ class manager {
|
||||
$task->get_lock()->release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the fail delay for the given task and updates its next run time based on the schedule.
|
||||
*
|
||||
* @param scheduled_task $task Task to reset
|
||||
* @throws \dml_exception If there is a database error
|
||||
*/
|
||||
public static function clear_fail_delay(scheduled_task $task) {
|
||||
global $DB;
|
||||
|
||||
$record = new \stdClass();
|
||||
$record->id = $DB->get_field('task_scheduled', 'id',
|
||||
['classname' => self::get_canonical_class_name($task)]);
|
||||
$record->nextruntime = $task->get_next_scheduled_time();
|
||||
$record->faildelay = 0;
|
||||
$DB->update_record('task_scheduled', $record);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function indicates that a scheduled task was completed successfully and should be rescheduled.
|
||||
*
|
||||
@ -681,10 +670,7 @@ class manager {
|
||||
public static function scheduled_task_complete(scheduled_task $task) {
|
||||
global $DB;
|
||||
|
||||
$classname = get_class($task);
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
$classname = self::get_canonical_class_name($task);
|
||||
$record = $DB->get_record('task_scheduled', array('classname' => $classname));
|
||||
if ($record) {
|
||||
$record->lastruntime = time();
|
||||
@ -731,4 +717,21 @@ class manager {
|
||||
$record = $DB->get_record('config', array('name'=>'scheduledtaskreset'));
|
||||
return $record && (intval($record->value) > $starttime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets class name for use in database table. Always begins with a \.
|
||||
*
|
||||
* @param string|task_base $taskorstring Task object or a string
|
||||
*/
|
||||
protected static function get_canonical_class_name($taskorstring) {
|
||||
if (is_string($taskorstring)) {
|
||||
$classname = $taskorstring;
|
||||
} else {
|
||||
$classname = get_class($taskorstring);
|
||||
}
|
||||
if (strpos($classname, '\\') !== 0) {
|
||||
$classname = '\\' . $classname;
|
||||
}
|
||||
return $classname;
|
||||
}
|
||||
}
|
||||
|
@ -467,4 +467,38 @@ class core_scheduled_task_testcase extends advanced_testcase {
|
||||
// There should only be two items in the array, '.' and '..'.
|
||||
$this->assertEquals(2, count($filesarray));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the function to clear the fail delay from a task works correctly.
|
||||
*/
|
||||
public function test_clear_fail_delay() {
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Get an example task to use for testing. Task is set to run every minute by default.
|
||||
$taskname = '\core\task\send_new_user_passwords_task';
|
||||
|
||||
// Pretend task started running and then failed 3 times.
|
||||
$before = time();
|
||||
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
|
||||
for ($i = 0; $i < 3; $i ++) {
|
||||
$task = \core\task\manager::get_scheduled_task($taskname);
|
||||
$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10);
|
||||
$task->set_lock($lock);
|
||||
\core\task\manager::scheduled_task_failed($task);
|
||||
}
|
||||
|
||||
// Confirm task is now delayed by several minutes.
|
||||
$task = \core\task\manager::get_scheduled_task($taskname);
|
||||
$this->assertEquals(240, $task->get_fail_delay());
|
||||
$this->assertGreaterThan($before + 230, $task->get_next_run_time());
|
||||
|
||||
// Clear the fail delay and re-get the task.
|
||||
\core\task\manager::clear_fail_delay($task);
|
||||
$task = \core\task\manager::get_scheduled_task($taskname);
|
||||
|
||||
// There should be no delay and it should run within the next minute.
|
||||
$this->assertEquals(0, $task->get_fail_delay());
|
||||
$this->assertLessThan($before + 70, $task->get_next_run_time());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user