Skip to content

Commit

Permalink
MDL-67433 tool_task: Add limits to adhoc CLI runner.
Browse files Browse the repository at this point in the history
  • Loading branch information
golenkovm committed Dec 18, 2019
1 parent 8cf4c97 commit 4234159
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 58 deletions.
50 changes: 9 additions & 41 deletions admin/tool/task/cli/adhoc_task.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
'keep-alive' => 0,
'showsql' => false,
'showdebugging' => false,
'ignorelimits' => false,
], [
'h' => 'help',
'e' => 'execute',
'k' => 'keep-alive',
'i' => 'ignorelimits',
]
);

Expand All @@ -57,6 +59,7 @@
--showdebugging Show developer level debugging information
-e, --execute Run all queued adhoc tasks
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
Example:
\$sudo -u www-data /usr/bin/php admin/tool/task/cli/adhoc_task.php --execute
Expand Down Expand Up @@ -99,6 +102,8 @@
set_debugging(DEBUG_DEVELOPER, true);
}

$checklimits = empty($options['ignorelimits']);

core_php_time_limit::raise();

// Increase memory limit.
Expand All @@ -107,45 +112,8 @@
// Emulate normal session - we use admin account by default.
cron_setup_user();

// Start output log.
$timestart = time();
$timenow = $timestart;
$finishtime = $timenow + (int)$options['keep-alive'];
$humantimenow = date('r', $timenow);
mtrace("Server Time: {$humantimenow}\n");

// Run all adhoc tasks.
$taskcount = 0;
$waiting = false;
while (!\core\task\manager::static_caches_cleared_since($timestart)) {

$task = \core\task\manager::get_next_adhoc_task($timenow);

if ($task) {
if ($waiting) {
cli_writeln('');
}
$waiting = false;
cron_run_inner_adhoc_task($task);
$taskcount++;
unset($task);
} else {
if (time() > $finishtime) {
break;
}
if (!$waiting) {
cli_write('Waiting for more adhoc tasks to be queued ');
} else {
cli_write('.');
}
$waiting = true;
sleep(1);
$timenow = time();
}
}
if ($waiting) {
cli_writeln('');
}

mtrace("Ran {$taskcount} adhoc tasks found at {$humantimenow}");
$humantimenow = date('r', time());
$keepalive = (int)$options['keep-alive'];

mtrace("Server Time: {$humantimenow}\n");
cron_run_adhoc_tasks(time(), $keepalive, $checklimits);
73 changes: 56 additions & 17 deletions lib/cronlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,41 +128,80 @@ function cron_run_scheduled_tasks(int $timenow) {
* Execute all queued adhoc tasks, applying necessary concurrency limits and time limits.
*
* @param int $timenow The time this process started.
* @param int $keepalive Keep this function alive for N seconds and poll for new adhoc tasks.
* @param bool $checklimits Should we check limits?
*/
function cron_run_adhoc_tasks(int $timenow) {
function cron_run_adhoc_tasks(int $timenow, $keepalive = 0, $checklimits = true) {
// Allow a restriction on the number of adhoc task runners at once.
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
$maxruns = get_config('core', 'task_adhoc_concurrency_limit');
$maxruntime = get_config('core', 'task_adhoc_max_runtime');

$adhoclock = null;
for ($run = 0; $run < $maxruns; $run++) {
if ($adhoclock = $cronlockfactory->get_lock("adhoc_task_runner_{$run}", 1)) {
break;
if ($checklimits) {
$adhoclock = null;
for ($run = 0; $run < $maxruns; $run++) {
if ($adhoclock = $cronlockfactory->get_lock("adhoc_task_runner_{$run}", 1)) {
break;
}
}
}

if (!$adhoclock) {
mtrace("Skipping processing of adhoc tasks. Concurrency limit reached.");
return;
if (!$adhoclock) {
mtrace("Skipping processing of adhoc tasks. Concurrency limit reached.");
return;
}
}

$starttime = time();
$humantimenow = date('r', $timenow);
$finishtime = $timenow + $keepalive;
$waiting = false;
$taskcount = 0;

// Run all adhoc tasks.
while (!\core\task\manager::static_caches_cleared_since($timenow) &&
$task = \core\task\manager::get_next_adhoc_task(time())) {
cron_run_inner_adhoc_task($task);
unset($task);
while (!\core\task\manager::static_caches_cleared_since($timenow)) {

if ((time() - $starttime) > $maxruntime) {
if ($checklimits && (time() - $timenow) >= $maxruntime) {
if ($waiting) {
$waiting = false;
mtrace('');
}
mtrace("Stopping processing of adhoc tasks as time limit has been reached.");
break;
}

$task = \core\task\manager::get_next_adhoc_task(time());

if ($task) {
if ($waiting) {
mtrace('');
}
$waiting = false;
cron_run_inner_adhoc_task($task);
$taskcount++;
unset($task);
} else {
if (time() >= $finishtime) {
break;
}
if (!$waiting) {
mtrace('Waiting for more adhoc tasks to be queued ', '');
} else {
mtrace('.', '');
}
$waiting = true;
sleep(1);
}
}

if ($waiting) {
mtrace('');
}

// Release the adhoc task runner lock.
$adhoclock->release();
mtrace("Ran {$taskcount} adhoc tasks found at {$humantimenow}");

if ($adhoclock) {
// Release the adhoc task runner lock.
$adhoclock->release();
}
}

/**
Expand Down
5 changes: 5 additions & 0 deletions lib/upgrade.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
This files describes API changes in core libraries and APIs,
information provided here is intended especially for developers.

=== 3.9 ===

* admin/tool/task/cli/adhoc_task.php now observers the concurrency limits.
If you want to get the previous (unlimited) behavior, use the --ignorelimits switch).

=== 3.8 ===
* Add CLI option to notify all cron tasks to stop: admin/cli/cron.php --stop
* The rotate_image function has been added to the stored_file class (MDL-63349)
Expand Down

0 comments on commit 4234159

Please sign in to comment.