Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 8 additions & 76 deletions src/Illuminate/Cache/PhpRedisLock.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
namespace Illuminate\Cache;

use Illuminate\Redis\Connections\PhpRedisConnection;
use Redis;
use UnexpectedValueException;

class PhpRedisLock extends RedisLock
{
/**
* The phpredis factory implementation.
*
* @var \Illuminate\Redis\Connections\PhpredisConnection
*/
protected $redis;

/**
* Create a new phpredis lock instance.
*
Expand All @@ -31,80 +36,7 @@ public function release()
LuaScripts::releaseLock(),
1,
$this->name,
$this->serializedAndCompressedOwner()
...$this->redis->serializeAndCompress([$this->owner])
);
}

/**
* Get the owner key, serialized and compressed.
*
* @return string
*/
protected function serializedAndCompressedOwner(): string
{
$client = $this->redis->client();

$owner = $client->_serialize($this->owner);

// 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;
}

/**
* Determine if compression is enabled.
*
* @return bool
*/
protected function compressed(): bool
{
return $this->redis->client()->getOption(Redis::OPT_COMPRESSION) !== Redis::COMPRESSION_NONE;
}

/**
* Determine if LZF compression is enabled.
*
* @return bool
*/
protected function lzfCompressed(): bool
{
return defined('Redis::COMPRESSION_LZF') &&
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZF;
}

/**
* Determine if ZSTD compression is enabled.
*
* @return bool
*/
protected function zstdCompressed(): bool
{
return defined('Redis::COMPRESSION_ZSTD') &&
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_ZSTD;
}

/**
* Determine if LZ4 compression is enabled.
*
* @return bool
*/
protected function lz4Compressed(): bool
{
return defined('Redis::COMPRESSION_LZ4') &&
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZ4;
}
}
93 changes: 93 additions & 0 deletions src/Illuminate/Redis/Connections/PhpRedisConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Redis;
use RedisCluster;
use RedisException;
use UnexpectedValueException;

/**
* @mixin \Redis
Expand Down Expand Up @@ -573,4 +574,96 @@ public function __call($method, $parameters)
{
return parent::__call(strtolower($method), $parameters);
}

/**
* Prepares values to be used with e.g. the `eval` command, because the
* phpredis extension does not do it for us.
*
* @param array<int,mixed> $values
* @return array<int,string>
*/
public function serializeAndCompress(array $values): array
{
if (empty($values)) {
return $values;
}

// https://github.com/phpredis/phpredis/issues/1938
if ($this->compressed()) {
if ($this->lzfCompressed()) {
$processor = function ($value) {
return \lzf_compress($this->client->_serialize($value));
};
} elseif ($this->zstdCompressed()) {
$compressionLevel = $this->client->getOption(Redis::OPT_COMPRESSION_LEVEL);
$processor = function ($value) use ($compressionLevel) {
return \zstd_compress(
$this->client->_serialize($value),
$compressionLevel === 0 ? Redis::COMPRESSION_ZSTD_DEFAULT : $compressionLevel
);
};
} elseif ($this->lz4Compressed()) {
$processor = function ($value) {
return \lz4_compress(
$this->client->_serialize($value),
$this->client->getOption(Redis::OPT_COMPRESSION_LEVEL)
);
};
} else {
throw new UnexpectedValueException(sprintf(
'Unknown phpredis compression in use [%d].',
$this->client->getOption(Redis::OPT_COMPRESSION)
));
}
} else {
$processor = function ($value) {
return $this->client->_serialize($value);
};
}

return array_map($processor, $values);
}

/**
* Determine if compression is enabled.
*
* @return bool
*/
protected function compressed(): bool
{
return $this->client->getOption(Redis::OPT_COMPRESSION) !== Redis::COMPRESSION_NONE;
}

/**
* Determine if LZF compression is enabled.
*
* @return bool
*/
protected function lzfCompressed(): bool
{
return defined('Redis::COMPRESSION_LZF') &&
$this->client->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZF;
}

/**
* Determine if ZSTD compression is enabled.
*
* @return bool
*/
protected function zstdCompressed(): bool
{
return defined('Redis::COMPRESSION_ZSTD') &&
$this->client->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_ZSTD;
}

/**
* Determine if LZ4 compression is enabled.
*
* @return bool
*/
protected function lz4Compressed(): bool
{
return defined('Redis::COMPRESSION_LZ4') &&
$this->client->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZ4;
}
}
24 changes: 24 additions & 0 deletions src/Illuminate/Redis/Connectors/PhpRedisConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ protected function createClient(array $config)
if (! empty($config['name'])) {
$client->client('SETNAME', $config['name']);
}

if (array_key_exists('serializer', $config)) {
$client->setOption(Redis::OPT_SERIALIZER, $config['serializer']);
}

if (array_key_exists('compression', $config)) {
$client->setOption(Redis::OPT_COMPRESSION, $config['compression']);
}

if (array_key_exists('compression_level', $config)) {
$client->setOption(Redis::OPT_COMPRESSION_LEVEL, $config['compression_level']);
}
});
}

Expand Down Expand Up @@ -184,6 +196,18 @@ protected function createRedisClusterInstance(array $servers, array $options)
if (! empty($options['name'])) {
$client->client('SETNAME', $options['name']);
}

if (array_key_exists('serializer', $options)) {
$client->setOption(RedisCluster::OPT_SERIALIZER, $options['serializer']);
}

if (array_key_exists('compression', $options)) {
$client->setOption(RedisCluster::OPT_COMPRESSION, $options['compression']);
}

if (array_key_exists('compression_level', $options)) {
$client->setOption(RedisCluster::OPT_COMPRESSION_LEVEL, $options['compression_level']);
}
});
}

Expand Down
Loading