1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
<?php
declare(strict_types=1);
namespace malkusch\lock\mutex;
use malkusch\lock\exception\LockAcquireException;
use malkusch\lock\exception\LockReleaseException;
use Predis\ClientInterface;
use Predis\PredisException;
/**
* Mutex based on the Redlock algorithm using the Predis API.
*
* @author Markus Malkusch <markus@malkusch.de>
* @license WTFPL
*
* @link http://redis.io/topics/distlock
* @link bitcoin:1P5FAZ4QhXCuwYPnLZdk3PJsqePbu1UDDA Donations
*/
class PredisMutex extends RedisMutex
{
/**
* Sets the Redis connections.
*
* @param ClientInterface[] $clients The Redis clients.
* @param string $name The lock name.
* @param int $timeout The time in seconds a lock expires, default is 3.
*
* @throws \LengthException The timeout must be greater than 0.
*/
public function __construct(array $clients, string $name, int $timeout = 3)
{
parent::__construct($clients, $name, $timeout);
}
/**
* @throws LockAcquireException
*/
protected function add($redisAPI, string $key, string $value, int $expire): bool
{
/** @var ClientInterface $redisAPI */
try {
return $redisAPI->set($key, $value, 'EX', $expire, 'NX') !== null;
} catch (PredisException $e) {
$message = sprintf(
"Failed to acquire lock for key '%s'",
$key
);
throw new LockAcquireException($message, 0, $e);
}
}
/**
* @throws LockReleaseException
*/
protected function evalScript($client, string $script, int $numkeys, array $arguments)
{
/** @var ClientInterface $client */
try {
return $client->eval($script, $numkeys, ...$arguments);
} catch (PredisException $e) {
throw new LockReleaseException('Failed to release lock', 0, $e);
}
}
}
|