fivesqrd / mutex
Shared locking library for multi server implementations
Requires
- php: >=5.4.0
Requires (Dev)
- aws/aws-sdk-php: ^3.29
- phpunit/phpunit: ^9.6
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Locking library for multi server implementations using distributed selection of execution.
Install
composer require fivesqrd/mutex:1.0.*
Basic usage
<?php
require_once realpath(__DIR__ . '/../vendor/autoload.php');
use Fivesqrd\Mutex;
$mutex = new Mutex\Factory([
'aws' => array(
'version' => '2012-08-10',
'region' => 'eu-west-1',
'endpoint' => 'http://192.168.254.10:8000',
'credentials' => array(
'key' => 'my-key',
'secret' => 'my-secret',
)
),
'namespace' => 'My-Example-App',
'table' => 'My-DynamoDb-Table',
// Optional. acquire() is atomic and does not sleep by default.
// Set this to spread a cron thundering herd (random delay in [0, N] ms).
'acquire_jitter_ms' => 0,
]);
echo date('Y-m-d H:i:s') . " Starting job\n";
if (!$mutex->lock(basename($argv[0]))->acquire(10)) {
echo "- The work slot for this job has been locked, skipping...\n";
exit;
}
echo "- Lock acquired successfully...\n";
acquire() returns false when another process holds an unexpired lock. Infrastructure errors (IAM, throttling, credentials, network) throw Fivesqrd\Mutex\Exception — they are not reported as contention. Keep the lock TTL longer than the work; this library prevents overlap, not duplicate sequential runs.
Ownership is hostname:pid (Owner on the item). extend() / release() only succeed for the process that acquired. release() returns false if this process does not own the item (including already gone). Drain 1.0.13 processes before relying on the race fix: old clients still write unconditionally.
Laravel 5
.env requirements
MUTEX_TABLE="My-Table"
MUTEX_NAMESPACE="My-App"
AWS_ACCESS_KEY_ID="my-key"
AWS_SECRET_ACCESS_KEY="my-secret"
AWS_DEFAULT_REGION="eu-west-1"
AWS_ENDPOINT=
MUTEX_ACQUIRE_JITTER_MS=0
Using it in a command class:
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if (!resolve('mutex')->lock(self::class)->acquire()) {
$this->info("Failed to acquire lock for this command");
return;
}
/* logic here */
$this->info("Command completed successfully");
}