Mutex for Laravel Console Commands.
Laravel | Console Mutex |
---|---|
11.x | Support ☕ |
10.x | 10.x |
9.x | 9.x |
8.x | 8.x |
7.x | 7.x |
6.x | 6.x |
5.8.* | 5.8.* |
5.7.* | 5.7.* |
5.6.* | 5.6.* |
5.5.* | 5.5.* |
5.4.* | 5.4.* |
5.3.* | 5.3.* |
5.2.* | 5.2.* |
5.1.* | 5.1.* |
-
Install the package via Composer:
composer require illuminated/console-mutex
-
Use
Illuminated\Console\WithoutOverlapping
trait:use Illuminated\Console\WithoutOverlapping; class ExampleCommand extends Command { use WithoutOverlapping; // ... }
Mutex can prevent overlapping by using various strategies:
file
(default)mysql
redis
memcached
The default file
strategy is acceptable for small applications, which are deployed on a single server.
If your application is more complex and deployed on several nodes, you should consider using another mutex strategy.
You can change strategy by using the $mutexStrategy
field:
class ExampleCommand extends Command
{
use WithoutOverlapping;
protected string $mutexStrategy = 'mysql';
// ...
}
Or by using the setMutexStrategy()
method:
class ExampleCommand extends Command
{
use WithoutOverlapping;
public function __construct()
{
parent::__construct();
$this->setMutexStrategy('mysql');
}
// ...
}
By default, if mutex sees that the command is already running, it will immediately quit. You can change that behavior by setting a timeout in which mutex can wait for another running command to finish its execution.
You can set the timeout by specifying the $mutexTimeout
field:
class ExampleCommand extends Command
{
use WithoutOverlapping;
// In milliseconds
protected ?int $mutexTimeout = 3000;
// ...
}
Or by using the setMutexTimeout()
method:
class ExampleCommand extends Command
{
use WithoutOverlapping;
public function __construct()
{
parent::__construct();
// In milliseconds
$this->setMutexTimeout(3000);
}
// ...
}
Here's how the $mutexTimeout
field is treated:
0
- no waiting (default);{int}
- wait for the given number of milliseconds;null
- wait for the running command to finish its execution;
Sometimes it might be useful to have a shared mutex for multiple commands. You can easily achieve that by setting the same mutex name for all of those commands.
You should use the getMutexName()
method for that:
class ExampleCommand extends Command
{
use WithoutOverlapping;
public function getMutexName()
{
return 'shared-for-command1-and-command2';
}
// ...
}
If you're using the file
strategy, mutex files would be stored in the storage/app
folder.
You can change that by overriding the getMutexFileStorage()
method:
class ExampleCommand extends Command
{
use WithoutOverlapping;
public function getMutexFileStorage()
{
return storage_path('my/custom/path');
}
// ...
}
WithoutOverlapping
trait overrides the initialize()
method:
trait WithoutOverlapping
{
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->initializeMutex();
parent::initialize($input, $output);
}
// ...
}
If your command overrides the initialize()
method too, you have to call the initializeMutex()
method by yourself:
class ExampleCommand extends Command
{
use WithoutOverlapping;
protected function initialize(InputInterface $input, OutputInterface $output)
{
// You have to call it first
$this->initializeMutex();
// Then goes your custom code
$this->foo = $this->argument('foo');
$this->bar = $this->argument('bar');
$this->baz = $this->argument('baz');
}
// ...
}
If you're using another illuminated/console-%
package, you'll get the "traits conflict" error.
For example, if you're building a loggable command, which doesn't allow overlapping:
class ExampleCommand extends Command
{
use Loggable;
use WithoutOverlapping;
// ...
}
You'll get the traits conflict, because both of those traits are overriding the initialize()
method:
If two traits insert a method with the same name, a fatal error is produced, if the conflict is not explicitly resolved.
To fix that - override the initialize()
method and resolve the conflict:
class ExampleCommand extends Command
{
use Loggable;
use WithoutOverlapping;
protected function initialize(InputInterface $input, OutputInterface $output)
{
// Initialize conflicting traits
$this->initializeMutex();
$this->initializeLogging();
}
// ...
}
Laravel Console Mutex is open-sourced software licensed under the MIT license.