mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 14:27:22 +01:00
a92e5c5770
If a quiz had a long job to calculate statstics running, this would cause pages that may also attempt a recalculation (the statistics report page or question bank) to load very slowly, and possibly result in a database deadlock. This change will firstly prevent the question bank page performing analysis calculations at all, since these are not required for this page, which will speed up loading and prevent deadlocks on this page. Secondly, this adds a lock to the recalcuation process so that it cannot run twice concurrently. This will present the user with a message to indicate that it is waiting for a running calculation until it is complete, and eventually it will timeout with a message and debugging.
77 lines
3.1 KiB
PHP
77 lines
3.1 KiB
PHP
<?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/>.
|
|
|
|
namespace core\lock;
|
|
|
|
use core\progress\base;
|
|
|
|
/**
|
|
* Lock utilities.
|
|
*
|
|
* @package core
|
|
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
|
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class lock_utils {
|
|
/**
|
|
* Start a progress bar and attempt to get a lock, updating the bar until a lock is achieved.
|
|
*
|
|
* This will make multiple attempts at getting the lock using a short timeout set by $progressupdatetime. After
|
|
* each failed attempt, it will update the progress bar and try again, until $timeout is reached.
|
|
*
|
|
* @param lock_factory $lockfactory The factory to use to get the lock
|
|
* @param string $resource The resource key we will try to get a lock on
|
|
* @param base $progress The progress bar
|
|
* @param int $timeout The maximum time in seconds to wait for a lock
|
|
* @param string $message Optional message to display on the progress bar
|
|
* @param int $progressupdatetime The number of seconds to wait for each lock attempt before updating the progress bar.
|
|
* @param int $maxlifetime The maxlifetime to set on the lock, if supported.
|
|
* @return lock|false A lock if successful, or false if the timeout expires.
|
|
* @throws \coding_exception
|
|
*/
|
|
public static function wait_for_lock_with_progress(
|
|
lock_factory $lockfactory,
|
|
string $resource,
|
|
\core\progress\base $progress,
|
|
int $timeout,
|
|
string $message = '',
|
|
int $progressupdatetime = 10,
|
|
int $maxlifetime = DAYSECS,
|
|
) {
|
|
if ($progressupdatetime < 1) {
|
|
throw new \invalid_parameter_exception('Progress bar cannot update more than once per second. ' .
|
|
'$progressupdate time must be at least 1.');
|
|
}
|
|
if ($progressupdatetime > $timeout) {
|
|
throw new \invalid_parameter_exception('$timeout must be greater than $progressupdatetime.');
|
|
}
|
|
$lockattempts = 0;
|
|
$maxattempts = $timeout / $progressupdatetime;
|
|
$lock = false;
|
|
$progress->start_progress($message);
|
|
while (!$lock && $lockattempts < $maxattempts) {
|
|
$lock = $lockfactory->get_lock($resource, $progressupdatetime, $maxlifetime);
|
|
if (!$lock) {
|
|
$progress->progress();
|
|
$lockattempts++;
|
|
}
|
|
}
|
|
$progress->end_progress();
|
|
return $lock;
|
|
}
|
|
}
|