You are here

public function PhpRedis::acquire in Redis 8

Acquires a lock.

Parameters

string $name: Lock name. Limit of name's length is 255 characters.

float $timeout: (optional) Lock lifetime in seconds. Defaults to 30.0.

Return value

bool

Overrides LockBackendInterface::acquire

File

src/Lock/PhpRedis.php, line 47

Class

PhpRedis
Predis lock backend implementation.

Namespace

Drupal\redis\Lock

Code

public function acquire($name, $timeout = 30.0) {
  $key = $this
    ->getKey($name);
  $id = $this
    ->getLockId();

  // Insure that the timeout is at least 1 ms.
  $timeout = max($timeout, 0.001);

  // If we already have the lock, check for his owner and attempt a new EXPIRE
  // command on it.
  if (isset($this->locks[$name])) {

    // Create a new transaction, for atomicity.
    $this->client
      ->watch($key);

    // Global tells us we are the owner, but in real life it could have expired
    // and another process could have taken it, check that.
    if ($this->client
      ->get($key) != $id) {

      // Explicit UNWATCH we are not going to run the MULTI/EXEC block.
      $this->client
        ->unwatch();
      unset($this->locks[$name]);
      return FALSE;
    }
    $result = $this->client
      ->multi()
      ->psetex($key, (int) ($timeout * 1000), $id)
      ->exec();

    // If the set failed, someone else wrote the key, we failed to acquire
    // the lock.
    if (FALSE === $result) {
      unset($this->locks[$name]);

      // Explicit transaction release which also frees the WATCH'ed key.
      $this->client
        ->discard();
      return FALSE;
    }
    return $this->locks[$name] = TRUE;
  }
  else {

    // Use a SET with microsecond expiration and the NX flag, which will only
    // succeed if the key does not exist yet.
    $result = $this->client
      ->set($key, $id, [
      'nx',
      'px' => (int) ($timeout * 1000),
    ]);

    // If the result is FALSE, we failed to acquire the lock.
    if (FALSE === $result) {
      return FALSE;
    }

    // Register the lock.
    return $this->locks[$name] = TRUE;
  }
}