Skip to content

Instantly share code, notes, and snippets.

@derekmd
Created February 27, 2021 23:45
Show Gist options
  • Save derekmd/039d1b7b83326fc69790552fb30c9cc8 to your computer and use it in GitHub Desktop.
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/
<?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