wordcoolframework/coolrace is a Laravel package for handle race condition.
It currently has 2 GitHub stars and 0 downloads on Packagist.
Install it with composer require wordcoolframework/coolrace.
Discover more Laravel packages by wordcoolframework
or browse all Laravel packages to compare alternatives.
Last updated
CoolRace is a PHP library designed to handle distributed locking in a Laravel application. It provides a flexible and robust way to manage locks for critical sections of code, ensuring that only one process can execute a given block of code at a time. The library supports various locking drivers and includes features like context prefixes, retries, and model-specific locking.
FileLockDriver).To use CoolRace in your Laravel project, follow these steps:
Require the Package Ensure your project uses PHP 7.4+ and Laravel 8.x or higher. Install the package via Composer:
composer require wordcoolframework/coolrace
Set Up the Lock Driver
Configure the lock driver (e.g., FileLockDriver) by providing a storage path for lock files. Update your configuration or service provider as needed.
Register the Service
If not automatically registered, bind CoolRace to your Laravel service container:
$this->app->singleton(CoolRace::class, function () {
return new CoolRace(new FileLockDriver(storage_path('locks')));
});
The CoolRace class provides several methods to manage locks. Below are the primary methods and their usage.
The lock method acquires a lock for a given key, executes a callback, and releases the lock afterward. If the lock cannot be acquired within the timeout, it throws a LockTimeoutException.
use Wordcoolframework\CoolRace\CoolRace;
$coolRace = new CoolRace(new FileLockDriver(storage_path('locks')));
$result = $coolRace->lock('my-resource', function () {
// Critical section
return 'Operation completed';
}, 10);
The tryLock method attempts to acquire a lock but returns null instead of throwing an exception if the lock cannot be acquired.
$result = $coolRace->tryLock('my-resource', function () {
return 'Operation completed';
}, 5);
if ($result === null) {
echo "Could not acquire lock";
} else {
echo $result;
}
The lockWithRetry method attempts to acquire a lock multiple times with a delay between attempts. If all retries fail, it throws a LockTimeoutException.
$result = $coolRace->lockWithRetry('my-resource', function () {
return 'Operation completed';
}, 10, 3, 500);
The lockForModel method creates a lock based on an Eloquent model's class name and primary key.
use App\Models\User;
$user = User::find(1);
$result = $coolRace->lockForModel($user, function () use ($user) {
$user->balance += 100;
$user->save();
return 'Balance updated';
});
The lockMultiple method acquires multiple locks in a sorted order to avoid deadlocks, executes the callback, and releases all locks.
$result = $coolRace->lockMultiple(['resource1', 'resource2'], function () {
return 'Multiple resources locked';
}, 10);
The withContext method creates a new instance with a prefix for all lock keys, useful for scoping locks.
$scopedCoolRace = $coolRace->withContext('user:123');
$result = $scopedCoolRace->lock('action', function () {
return 'Scoped operation';
});
The isLocked method checks if a lock is currently held.
if ($coolRace->isLocked('my-resource')) {
echo "Resource is locked";
} else {
echo "Resource is available";
}
Use acquire and release for manual lock management without a callback.
if ($coolRace->acquire('my-resource', 10)) {
try {
// Critical section
} finally {
$coolRace->release('my-resource');
}
}
The forceReleaseAllByPrefix method releases all locks matching a given prefix (if supported by the driver).
$coolRace->forceReleaseAllByPrefix('user:123');
The lockUntil method acquires a lock with a timeout based on a DateTimeInterface instance.
$until = new \DateTime('+1 minute');
$result = $coolRace->lockUntil('my-resource', function () {
return 'Operation completed';
}, $until);
Here’s a practical example of using CoolRace to prevent double payments for an order:
use Wordcoolframework\CoolRace\CoolRace;
use App\Models\Order;
$coolRace = app(CoolRace::class);
$order = Order::find(123);
$result = $coolRace->lockForModel($order, function () use ($order) {
if ($order->is_paid) {
throw new Exception('Order already paid');
}
// Process payment
$order->is_paid = true;
$order->save();
return 'Payment processed';
});
echo $result;
The FileLockDriver is a simple file-based locking driver included with CoolRace. It stores lock files in a specified directory and uses file creation as a locking mechanism.
use Wordcoolframework\CoolRace\Drivers\FileLockDriver;
$driver = new FileLockDriver(storage_path('locks'));
$coolRace = new CoolRace($driver);
releaseAllByPrefix method deletes all lock files matching the given prefix.lock and lockWithRetry when a lock cannot be acquired within the timeout or retries.try {
$result = $coolRace->lock('my-resource', function () {
return 'Operation completed';
});
} catch (LockTimeoutException $e) {
echo "Failed to acquire lock: " . $e->getMessage();
}
Contributions are welcome! Please submit pull requests or issues to the GitHub repository.
This project is licensed under the MIT License.