-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#36337: Respect serialization and compression of phpredis during locking
- Support phpredis serialization when locking (none, php, json, igbinary, msgpack). - Support phpredis compression when locking (none, lzf, zstd, lz4).
- Loading branch information
Showing
3 changed files
with
435 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
<?php | ||
|
||
namespace Illuminate\Cache; | ||
|
||
use Illuminate\Redis\Connections\PhpRedisConnection; | ||
use Redis; | ||
use UnexpectedValueException; | ||
|
||
class PhpRedisLock extends RedisLock | ||
{ | ||
/** | ||
* Create a new phpredis lock instance. | ||
* | ||
* @param \Illuminate\Redis\Connections\PhpRedisConnection $redis | ||
* @param string $name | ||
* @param int $seconds | ||
* @param string|null $owner | ||
* @return void | ||
*/ | ||
public function __construct(PhpRedisConnection $redis, string $name, int $seconds, ?string $owner = null) | ||
{ | ||
parent::__construct($redis, $name, $seconds, $owner); | ||
} | ||
|
||
/** | ||
* Release the lock. | ||
* | ||
* @return bool | ||
*/ | ||
public function release() | ||
{ | ||
return (bool) $this->redis->eval( | ||
LuaScripts::releaseLock(), | ||
1, | ||
$this->name, | ||
$this->serializedAndCompressedOwner() | ||
); | ||
} | ||
|
||
protected function serializedAndCompressedOwner(): string | ||
{ | ||
$client = $this->redis->client(); | ||
|
||
/* If a serialization mode such as "php" or "igbinary" and/or a | ||
* compression mode such as "lzf" or "zstd" is enabled, the owner | ||
* must be serialized and/or compressed by us, because phpredis does | ||
* not do this for the eval command. | ||
* | ||
* Name must not be modified! | ||
*/ | ||
$owner = $client->_serialize($this->owner); | ||
|
||
/* Once the phpredis extension exposes a compress function like the | ||
* above `_serialize()` function, we should switch to it to guarantee | ||
* consistency in the way the extension serializes and compresses to | ||
* avoid the need to check each compression option ourselves. | ||
* | ||
* @see https://github.com/phpredis/phpredis/issues/1938 | ||
*/ | ||
if ($this->compressed()) { | ||
if ($this->lzfCompressed()) { | ||
$owner = \lzf_compress($owner); | ||
} elseif ($this->zstdCompressed()) { | ||
$owner = \zstd_compress($owner, $client->getOption(Redis::OPT_COMPRESSION_LEVEL)); | ||
} elseif ($this->lz4Compressed()) { | ||
$owner = \lz4_compress($owner, $client->getOption(Redis::OPT_COMPRESSION_LEVEL)); | ||
} else { | ||
throw new UnexpectedValueException(sprintf( | ||
'Unknown phpredis compression in use (%d). Unable to release lock.', | ||
$client->getOption(Redis::OPT_COMPRESSION) | ||
)); | ||
} | ||
} | ||
|
||
return $owner; | ||
} | ||
|
||
/** | ||
* Determines whether compression is enabled for the phpredis connection. | ||
* | ||
* @return bool | ||
*/ | ||
protected function compressed() | ||
{ | ||
return $this->redis->client()->getOption(Redis::OPT_COMPRESSION) !== Redis::COMPRESSION_NONE; | ||
} | ||
|
||
/** | ||
* Determines whether lzf compression is enabled for the phpredis connection. | ||
* | ||
* @return bool | ||
*/ | ||
protected function lzfCompressed() | ||
{ | ||
return defined('Redis::COMPRESSION_LZF') && | ||
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZF; | ||
} | ||
|
||
/** | ||
* Determines whether zstd compression is enabled for the phpredis connection. | ||
* | ||
* @return bool | ||
*/ | ||
protected function zstdCompressed() | ||
{ | ||
return defined('Redis::COMPRESSION_ZSTD') && | ||
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_ZSTD; | ||
} | ||
|
||
/** | ||
* Determines whether lz4 compression is enabled for the phpredis connection. | ||
* | ||
* @return bool | ||
*/ | ||
protected function lz4Compressed() | ||
{ | ||
return defined('Redis::COMPRESSION_LZ4') && | ||
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZ4; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.