Created
February 27, 2021 23:45
-
-
Save derekmd/039d1b7b83326fc69790552fb30c9cc8 to your computer and use it in GitHub Desktop.
Code refactor of class RedisLock from https://github.com/laravel/framework/pull/36412/
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
<?php | |
namespace Illuminate\Cache; | |
use Redis; | |
use RedisCluster; | |
use UnexpectedValueException; | |
class RedisLock extends Lock | |
{ | |
/** | |
* The Redis factory implementation. | |
* | |
* @var \Illuminate\Redis\Connections\Connection | |
*/ | |
protected $redis; | |
/** | |
* Create a new lock instance. | |
* | |
* @param \Illuminate\Redis\Connections\Connection $redis | |
* @param string $name | |
* @param int $seconds | |
* @param string|null $owner | |
* @return void | |
*/ | |
public function __construct($redis, $name, $seconds, $owner = null) | |
{ | |
parent::__construct($name, $seconds, $owner); | |
$this->redis = $redis; | |
} | |
/** | |
* Attempt to acquire the lock. | |
* | |
* @return bool | |
*/ | |
public function acquire() | |
{ | |
if ($this->seconds > 0) { | |
return $this->redis->set($this->name, $this->owner, 'EX', $this->seconds, 'NX') == true; | |
} else { | |
return $this->redis->setnx($this->name, $this->owner) === 1; | |
} | |
} | |
/** | |
* Release the lock. | |
* | |
* @return bool | |
*/ | |
public function release() | |
{ | |
return (bool) $this->redis->eval(LuaScripts::releaseLock(), 1, $this->name, $this->phpRedisOwner() ?? $owner); | |
} | |
/** | |
* Releases this lock in disregard of ownership. | |
* | |
* @return void | |
*/ | |
public function forceRelease() | |
{ | |
$this->redis->del($this->name); | |
} | |
/** | |
* Returns the owner value written into the driver for this lock. | |
* | |
* @return string | |
*/ | |
protected function getCurrentOwner() | |
{ | |
return $this->redis->get($this->name); | |
} | |
/** | |
* Get the name of the Redis connection being used to manage the lock. | |
* | |
* @return string | |
*/ | |
public function getConnectionName() | |
{ | |
return $this->redis->getName(); | |
} | |
/** | |
* 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. | |
* | |
* @return string|null | |
* | |
* @throws \UnexpectedValueException | |
*/ | |
protected function phpRedisOwner() | |
{ | |
if (! $this->isPhpRedisCompressionEnabled()) { | |
return; | |
} | |
$owner = $this->redis->client()->_serialize($this->owner); | |
if ($this->isPhpRedisLzfEnabled()) { | |
return \lzf_compress($owner); | |
} elseif ($this->isPhpRedisZstdEnabled()) { | |
return \zstd_compress( | |
$owner, | |
$this->redis->client()->getOption(Redis::OPT_COMPRESSION_LEVEL) | |
); | |
} elseif ($this->isPhpRedisLz4Enabled()) { | |
return \lz4_compress( | |
$owner, | |
$this->redis->client()->getOption(Redis::OPT_COMPRESSION_LEVEL) | |
); | |
} else { | |
throw new UnexpectedValueException( | |
vsprintf('Unknown phpredis compression in use (%d). Unable to release lock.', [ | |
$this->redis->client()->getOption(Redis::OPT_COMPRESSION), | |
]) | |
); | |
} | |
} | |
/** | |
* Determines whether the client used to connect to redis is one from the | |
* phpredis extension. | |
* | |
* @return bool | |
*/ | |
protected function isPhpRedis() | |
{ | |
$client = $this->redis->client(); | |
return $client instanceof Redis || $client instanceof RedisCluster; | |
} | |
/** | |
* Determines whether compression is enabled for the phpredis connection. | |
* | |
* @return bool | |
*/ | |
protected function isPhpRedisCompressionEnabled() | |
{ | |
return $this->redis->client()->getOption(Redis::OPT_COMPRESSION) !== Redis::COMPRESSION_NONE; | |
} | |
/** | |
* Determines whether lz4 compression is enabled for the phpredis connection. | |
* | |
* @return bool | |
*/ | |
protected function isPhpRedisLz4Enabled() | |
{ | |
return defined('Redis::COMPRESSION_LZ4') && | |
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZ4; | |
} | |
/** | |
* Determines whether lzf compression is enabled for the phpredis connection. | |
* | |
* @return bool | |
*/ | |
protected function isPhpRedisLzfEnabled() | |
{ | |
return $this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_LZF; | |
} | |
/** | |
* Determines whether zstd compression is enabled for the phpredis connection. | |
* | |
* @return bool | |
*/ | |
protected function isPhpRedisZstdEnabled() | |
{ | |
return defined('Redis::COMPRESSION_ZSTD') && | |
$this->redis->client()->getOption(Redis::OPT_COMPRESSION) === Redis::COMPRESSION_ZSTD; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment