chrisharrison / lock
Avoid simultaneous execution of PHP code by first gaining a lock.
Installs: 2 829
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 2
Forks: 1
Open Issues: 0
Requires
- php: ^7.2
- chrisharrison/clock: ^1.0
Requires (Dev)
- phpunit/phpunit: ^8.2
- squizlabs/php_codesniffer: ^3.4
This package is auto-updated.
Last update: 2024-10-13 21:23:44 UTC
README
Avoid simultaneous execution of PHP code by first gaining a lock.
Installation
Through Composer, obviously:
composer require chrisharrison/lock
Why?
If you have code that will potentially cause an unwanted race condition when two parallel processed run it at the same time, you may want to introduce a lock so that only one process can execute that code while others wait.
Usage
First create a LockGuard
:
$lockGuard = new LockGuard(
$maxAttempts,
$attemptIntervalSeconds,
$lockDriver,
$lockInspector
);
$maxAttempts
:int
Maximum number of attempts to gain a lock before it gives up.$attemptIntervalSeconds
:int
Number of seconds between attempts to gain a lock$lockDriver
:LockDriver
An instance of a class which deals with persisting the lock to whatever storage mechanism$lockInspector
:LockInspector
An instance of a class which deals with testing validity of a lock
Once you've create a LockGuard
you can use it to protect code within a lock:
$flag = false;
$uniqueProcessId = '<ANY-UNIQUE-STRING>';
$lockUntil = DateTimeImmutable::createFromFormat('U', time()+300); // In 5 mins time
$didExecute = $lockGuard->protect('uniq-process-id', $lockUnitl, function () use (&$flag) {
$flag = true;
});
The above will attempt to set $flag
to true
.
If there is a lock that hasn't expired and was not created by the same process (identified by $uniqueProcessId
) then the code will execute and the method will return true
. Else false
.
As soon as the code has been successfully executed, the lock will be released. This happens even if the $lockUntil
time has not been reached. However if the code hasn't completed after the $lockUntil
time has been reached then the lock will expire and other processes can execute again. This is to mitigate situations where a lock is never released.
Typical usage
$lockPath = 'lock.json';
$maxAttempts = 5;
$attemptIntervalSeconds = 3;
$lockDriver = new FilesystemLockDriver($lockPath);
$lockInspector = new DefaultLockInspector;
$lockGuard = new LockGuard(
$maxAttempts,
$attemptIntervalSeconds,
$lockDriver,
$lockInspector
);
The FilesystemLockDriver
persists the lock as JSON to a file using the local filesystem.
You could create other LockDriver
s that use other methods, such as FlySystem to make use of S3.