protected function acquire($key, $expire)
{
// 1. This differs from the specification to avoid an overflow on 32-Bit systems.
$time = microtime(true);
// 2.
$acquired = 0;
$errored = 0;
$this->token = rand();
$exception = null;
foreach ($this->redisAPIs as $redis) {
try {
if ($this->add($redis, $key, $this->token, $expire)) {
$acquired++;
}
} catch (LockAcquireException $exception) {
$context = ["key" => $key, "token" => $this->token, "redis" => $this->getRedisIdentifier($redis), "exception" => $exception];
$this->logger->warning("Could not set {key} = {token} at {redis}.", $context);
$errored++;
}
}
// 3.
$elapsedTime = microtime(true) - $time;
$isAcquired = $this->isMajority($acquired) && $elapsedTime <= $expire;
if ($isAcquired) {
// 4.
return true;
} else {
// 5.
$this->release($key);
// In addition to RedLock it's an exception if too many servers fail.
if (!$this->isMajority(count($this->redisAPIs) - $errored)) {
assert(!is_null($exception));
// The last exception for some context.
throw new LockAcquireException("It's not possible to acquire a lock because at least half of the Redis server are not available.", LockAcquireException::REDIS_NOT_ENOUGH_SERVERS, $exception);
}
return false;
}
}