Download the PHP package brick/lock without Composer
On this page you can find all versions of the php package brick/lock. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package lock
Brick\Lock
Advisory locking for PHP applications.
Overview
This library provides a simple interface to work with advisory (named) locks for inter-process synchronization.
It works by using a database (MySQL, MariaDB or PostgreSQL) as a backend for locks. This allows the locks to work across multiple processes, and even across different web servers. It uses the native advisory locking functionality of each database (GET_LOCK() on MySQL / MariaDB, pg_advisory_lock() on PostgreSQL).
Locks are tied to the database connection they were created with, and are automatically released when the connection is closed, which prevents locks from remaining unreleased after a crash or a bug.
Locks are not affected by transactions, so it is safe to use your existing database connection.
Installation
This library is installable via Composer:
Requirements
This library requires PHP 8.2 or later.
Project status & release process
This library is under development and its API may evolve, but it is well-tested and considered ready for production use.
The current releases are numbered 0.x.y. When a non-breaking change is introduced (adding new methods, optimizing existing code, etc.), y is incremented.
When a breaking change is introduced, a new 0.x version cycle is always started.
It is therefore safe to lock your project to a given release cycle, such as 0.1.*.
If you need to upgrade to a newer release cycle, check the release history for a list of changes introduced by each further 0.x.0 version.
Usage
You first need to instantiate a lock driver. For example, to use MySQL over a PDO connection:
[!TIP] Available connections:
PdoConnection,DoctrineConnection
Available drivers:MysqlLockDriver,MariadbLockDriver,PostgresLockDriver
You can then instantiate the lock factory, which is the entry point to create named locks:
You can now create a lock object using a unique name that identifies the resource you want to lock:
And use it to acquire a lock:
The LockInterface object
The object returned by createLock() implements LockInterface, which provides the following methods:
-
acquire(): voidAcquires the lock, blocking until it is available.
-
tryAcquire(): boolTries to acquire the lock, non-blocking.
If the lock can be acquired immediately, this method returns
trueand the lock is held. If the lock is currently held by another process, this method returnsfalseand does not hold the lock. -
tryAcquireWithTimeout(int $seconds): boolTries to acquire the lock, with a maximum wait time.
If the lock can be acquired before the timeout expires, this method returns
trueand the lock is held. If the lock cannot be acquired before the timeout expires, this method returnsfalseand does not hold the lock. -
release(): voidReleases the lock.
Attempting to release a lock that is not held throws a
LockReleaseException. -
wait(): voidWaits until the lock is available, without acquiring it.
This can be used after an unsuccessful
tryAcquire()attempt, to wait for the result of the same operation performed by another process. -
tryWaitWithTimeout(int $seconds): boolWaits until the lock is available, or the timeout expires.
This method does not acquire the lock.
-
synchronize<T>(Closure(): T $task): TExecutes the given task while holding the lock.
Once the lock is acquired, the closure is executed, and its return value is returned as is. If the closure throws an exception, the lock is released and the exception bubbles up. This method is blocking and will wait for the lock to become available.
-
trySynchronize<T>(Closure(): T $task): SynchronizeSuccess<T>|nullExecutes the given task while holding the lock, non-blocking.
If the lock is available immediately, it is acquired, the closure is executed, and its return value is returned wrapped in a
SynchronizeSuccessobject. If the lock is currently held by another process, this method returnsnull. If the closure throws an exception, the lock is released and the exception bubbles up. -
trySynchronizeWithTimeout<T>(int $seconds, Closure(): T $task): SynchronizeSuccess<T>|nullExecutes the given task while holding the lock, with a maximum wait time.
If the lock is successfully acquired before the timeout expires, the closure is executed, and its return value is returned wrapped in a
SynchronizeSuccessobject. If the lock cannot be acquired before the timeout expires, this method returnsnull. If the closure throws an exception, the lock is released and the exception bubbles up.
Acquiring multiple locks
If you need to acquire multiple locks at once, use:
The object returned by createMultiLock() implements the same LockInterface as the single lock, so you can use it in exactly the same way.
The locks are acquired atomically, i.e. either all locks are acquired, or none of them are.
Reentrancy
Locks in this library are reentrant (also known as recursive locks), meaning the same process can acquire a lock multiple times without causing a deadlock. This is particularly useful for recursive methods that call themselves, or when methods call other methods that also need the same lock.
How It Works
- Each time a process acquires a reentrant lock, an internal counter is incremented
- The lock is only fully released when the counter returns to zero
- Other processes must wait until the lock is completely released before they can acquire it
Exceptions
Depending on the operation called, the following exceptions may be thrown:
LockAcquireExceptionLockReleaseExceptionLockWaitException
All of these exceptions extend LockException, which can be used to catch all lock-related exceptions.
These exceptions are only thrown when an error occurs, not in normal conditions like failure to acquire a lock due
to another process holding it. For example, tryAcquire() will return false if the lock cannot be acquired
immediately, and only throw a LockAcquireException if an error occurs and the status of the lock cannot be determined.
[!TIP] Check the source code of
LockInterfacefor detailed information about the exceptions thrown by each method.
Use in a Symfony project
In a Symfony project, add the following config, typically in config/services.yaml:
[!TIP] In a typical Symfony project using the Doctrine ORM, you'll probably want to use
DoctrineConnection.
You can now type-hint the Brick\Lock\LockFactoryInterface service in your code and use it to create locks.
Alternatives
You may also want to consider the following projects:
Please see the alternatives documentation for a detailed comparison of these libraries with brick/lock.