Lock
The lock subsystem serves to ensure the synchronization of various system processes and cron jobs. An example can be data synchronization or price recalculation on an e-shop. These are processes that are run periodically, can take a longer time, and at the same time, it is undesirable for another such process to start while one is already running.
Like everything in PHP Jet, this system is modular. A very simple and easy-to-use facade is used in the application, and behind it is a backend module that can be easily extended, replaced, or created as a completely custom implementation.
Using Locks
There are two options for using a lock: Immediate lock and waiting lock.
Immediate lock attempts to lock the given process, and if it is not possible (the lock is already held by another running process), it immediately returns false. It is up to the application to handle the situation when it cannot acquire the lock—most likely by printing a message and terminating the process.
Here is an example of usage:
use Jet\Lock;
if(!Lock::lockIfPossible( 'example-lock' )) {
die("Unable to lock. End.\n");
}
echo "Got lock, working ...\n";
for($c=0;$c<30;$c++) {
echo $c.".";
sleep(1);
}
echo "\n\nDone - unlock\n";
Lock::unlock( 'example-lock' );
Waiting lock attempts to lock, but if it fails, it tries again. However, it also has a defined time limit during which it can wait for the lock. If it fails to acquire the lock even after the limit expires, it again returns false, and the application—just like in the previous case—should, for example, terminate the process.
Here is another example of usage:
echo "Waiting for lock ....\n";
if(!Lock::waitForLock( 'example-lock', 10 )) {
die("Unable to lock. End.\n");
}
echo "Got lock, working ...\n";
for($c=0;$c<30;$c++) {
echo $c.".";
sleep(1);
}
echo "\n\nDone - unlock\n";
Lock::unlock( 'example-lock' );
As can be seen from the examples, unlocking a lock is done simply by calling the method Lock::unlock( 'example-lock' ); however, that is not all. The system features protection against deadlocks.
The first level of protection is that a shutdown function is always registered upon acquiring a lock to ensure the lock is released. This resolves situations where a process fails for an unforeseen reason—so-called crashes—and leaving a dead lock in the system could cause issues.
The second level of protection is handled by the lock backends themselves. A backend such as Jet\Lock_Backend_MariaDB has a maximum time limit set for how long it can hold a specific lock locked.
Lock Subsystem Configuration
The basic configuration involves specifying which backend will handle the locks. This is done in the initialization script application/Init/Lock.php as follows:
use Jet\Lock;
use Jet\Lock_Backend_MariaDB;
Lock::setLockBackendClass( Lock_Backend_MariaDB::class );
Locks are a low-level concern that should have minimal latency. Therefore, it is typically a very simple and, above all, self-contained system. That is why the configuration is similarly independent and straightforward.