DatabaseLock.php
TLDR
This file, DatabaseLock.php
, is part of the Illuminate\Cache
namespace and defines a class called DatabaseLock
that extends the Lock
class. It is responsible for acquiring, releasing, and managing locks using a database connection.
Methods
__construct(Connection $connection, $table, $name, $seconds, $owner = null, $lottery = [2, 100], $defaultTimeoutInSeconds = 86400)
This method is the constructor for the DatabaseLock
class. It initializes the instance variables of the class such as the database connection, table name, lock name, timeout duration in seconds, lock owner, and lottery odds. The Connection
class is a dependency and should be provided for proper instantiation.
acquire(): bool
This method attempts to acquire the lock. It first tries to insert a new lock record into the database table. If a QueryException
is caught, it means that a lock record with the same name already exists in the table. In this case, the method updates the existing lock record with the current owner and expiration time. If the update process is successful, the lock is considered acquired. The method also deletes expired lock records from the table based on the provided lottery odds. It returns a boolean value indicating whether the lock was acquired or not.
expiresAt(): int
This protected method returns a UNIX timestamp indicating when the lock should expire. It calculates the expiration time based on the lock duration ($this->seconds
) set during object instantiation. If no duration was set ($this->seconds
is 0), it uses the default timeout duration ($this->defaultTimeoutInSeconds
) provided during object instantiation.
release(): bool
This method releases the lock by deleting the lock record from the database table. It checks if the lock is owned by the current process before performing the delete operation. It returns a boolean value indicating whether the release was successful or not.
forceRelease(): void
This method forcefully releases the lock by deleting the lock record from the database table without checking ownership.
getCurrentOwner(): string
This protected method retrieves the current lock owner value written into the database for this lock. It queries the lock record from the database table based on the lock name and returns the owner value.
getConnectionName(): string
This method returns the name of the database connection being used to manage the lock.
Classes
The DatabaseLock
class does not have any additional classes defined within it.
<?php
namespace Illuminate\Cache;
use Illuminate\Database\Connection;
use Illuminate\Database\QueryException;
class DatabaseLock extends Lock
{
/**
* The database connection instance.
*
* @var \Illuminate\Database\Connection
*/
protected $connection;
/**
* The database table name.
*
* @var string
*/
protected $table;
/**
* The prune probability odds.
*
* @var array
*/
protected $lottery;
/**
* The default number of seconds that a lock should be held.
*
* @var int
*/
protected $defaultTimeoutInSeconds;
/**
* Create a new lock instance.
*
* @param \Illuminate\Database\Connection $connection
* @param string $table
* @param string $name
* @param int $seconds
* @param string|null $owner
* @param array $lottery
* @return void
*/
public function __construct(Connection $connection, $table, $name, $seconds, $owner = null, $lottery = [2, 100], $defaultTimeoutInSeconds = 86400)
{
parent::__construct($name, $seconds, $owner);
$this->connection = $connection;
$this->table = $table;
$this->lottery = $lottery;
$this->defaultTimeoutInSeconds = $defaultTimeoutInSeconds;
}
/**
* Attempt to acquire the lock.
*
* @return bool
*/
public function acquire()
{
try {
$this->connection->table($this->table)->insert([
'key' => $this->name,
'owner' => $this->owner,
'expiration' => $this->expiresAt(),
]);
$acquired = true;
} catch (QueryException) {
$updated = $this->connection->table($this->table)
->where('key', $this->name)
->where(function ($query) {
return $query->where('owner', $this->owner)->orWhere('expiration', '<=', time());
})->update([
'owner' => $this->owner,
'expiration' => $this->expiresAt(),
]);
$acquired = $updated >= 1;
}
if (random_int(1, $this->lottery[1]) <= $this->lottery[0]) {
$this->connection->table($this->table)->where('expiration', '<=', time())->delete();
}
return $acquired;
}
/**
* Get the UNIX timestamp indicating when the lock should expire.
*
* @return int
*/
protected function expiresAt()
{
$lockTimeout = $this->seconds > 0 ? $this->seconds : $this->defaultTimeoutInSeconds;
return time() + $lockTimeout;
}
/**
* Release the lock.
*
* @return bool
*/
public function release()
{
if ($this->isOwnedByCurrentProcess()) {
$this->connection->table($this->table)
->where('key', $this->name)
->where('owner', $this->owner)
->delete();
return true;
}
return false;
}
/**
* Releases this lock in disregard of ownership.
*
* @return void
*/
public function forceRelease()
{
$this->connection->table($this->table)
->where('key', $this->name)
->delete();
}
/**
* Returns the owner value written into the driver for this lock.
*
* @return string
*/
protected function getCurrentOwner()
{
return optional($this->connection->table($this->table)->where('key', $this->name)->first())->owner;
}
/**
* Get the name of the database connection being used to manage the lock.
*
* @return string
*/
public function getConnectionName()
{
return $this->connection->getName();
}
}