mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 14:03:52 +01:00
MDL-69684 session: Redis session locks set with expiry atomically
Co-Authored-By: Jamie Chapman-Brown <jamie.chapman-brown@agilicus.com> Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
This commit is contained in:
parent
cc2edf3b8c
commit
0d0cdaeecf
@ -53,6 +53,15 @@ class redis extends handler implements SessionHandlerInterface {
|
||||
*/
|
||||
const COMPRESSION_ZSTD = 'zstd';
|
||||
|
||||
/**
|
||||
* Minimum version of the Redis extension required.
|
||||
*/
|
||||
private const REDIS_EXTENSION_MIN_VERSION = '2.2.4';
|
||||
/**
|
||||
* Minimum version of the Redis extension required.
|
||||
*/
|
||||
private const REDIS_SERVER_MIN_VERSION = '2.6.12';
|
||||
|
||||
/** @var array $host save_path string */
|
||||
protected array $host = [];
|
||||
/** @var int $port The port to connect to */
|
||||
@ -201,13 +210,14 @@ class redis extends handler implements SessionHandlerInterface {
|
||||
|
||||
if (empty($this->host)) {
|
||||
throw new exception('sessionhandlerproblem', 'error', '', null,
|
||||
'$CFG->session_redis_host must be specified in config.php');
|
||||
'$CFG->session_redis_host must be specified in config.php');
|
||||
}
|
||||
|
||||
// The session handler requires a version of Redis with the SETEX command (at least 2.0).
|
||||
// The session handler requires a version of PHP Redis extension with support for SET command options (at least 2.2.4).
|
||||
$version = phpversion('Redis');
|
||||
if (!$version || version_compare($version, '2.0') <= 0) {
|
||||
throw new exception('sessionhandlerproblem', 'error', '', null, 'redis extension version must be at least 2.0');
|
||||
if (!$version || version_compare($version, self::REDIS_EXTENSION_MIN_VERSION) <= 0) {
|
||||
throw new exception('sessionhandlerproblem', 'error', '', null,
|
||||
'redis extension version must be at least ' . self::REDIS_EXTENSION_MIN_VERSION);
|
||||
}
|
||||
|
||||
$result = session_set_save_handler($this);
|
||||
@ -296,6 +306,13 @@ class redis extends handler implements SessionHandlerInterface {
|
||||
throw new $exceptionclass('Unable to select the Redis database ' . $this->database . '.');
|
||||
}
|
||||
}
|
||||
|
||||
// The session handler requires a version of Redis server with support for SET command options (at least 2.6.12).
|
||||
$serverversion = $this->connection->info('server')['redis_version'];
|
||||
if (version_compare($serverversion, self::REDIS_SERVER_MIN_VERSION) <= 0) {
|
||||
throw new exception('sessionhandlerproblem', 'error', '', null,
|
||||
'redis server version must be at least ' . self::REDIS_SERVER_MIN_VERSION);
|
||||
}
|
||||
return true;
|
||||
} catch (RedisException | RedisClusterException $e) {
|
||||
$redishost = $this->clustermode ? implode(',', $this->host) : $server. ':'. $port;
|
||||
@ -543,12 +560,10 @@ class redis extends handler implements SessionHandlerInterface {
|
||||
$haswarned = false; // Have we logged a lock warning?
|
||||
|
||||
while (!$haslock) {
|
||||
|
||||
$haslock = $this->connection->setnx($lockkey, $whoami);
|
||||
$haslock = $this->connection->set($lockkey, $whoami, ['nx', 'ex' => $this->lockexpire]);
|
||||
|
||||
if ($haslock) {
|
||||
$this->locks[$id] = $this->time() + $this->lockexpire;
|
||||
$this->connection->expire($lockkey, $this->lockexpire);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ information provided here is intended especially for developers.
|
||||
|
||||
=== 4.4.2 ===
|
||||
|
||||
* Redis session cache has been improved to make a single call where two were used before. The minimum redis version is now 2.6.12.
|
||||
* The `\core\dataformat::get_format_instance` method is now public, and can be used to retrieve a writer instance for
|
||||
a given dataformat
|
||||
* Added the ability for unit tests to autoload classes in the `\[component]\tests\` namespace from the `[path/to/component]/tests/classes` directory.
|
||||
|
Loading…
x
Reference in New Issue
Block a user