laravel-console-mutex
                                
                                 laravel-console-mutex copied to clipboard
                                
                                    laravel-console-mutex copied to clipboard
                            
                            
                            
                        Mutex for Laravel Console Commands.

Laravel Console Mutex
Mutex for Laravel Console Commands.
| Laravel | Console Mutex | 
|---|---|
| 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.* | 

Table of contents
- Usage
- Strategies
- Advanced
- Set custom timeout
- Handle multiple commands
- Set custom storage folder
 
- Troubleshooting
- Trait included, but nothing happens?
- Several traits conflict?
 
- Sponsors
- License
Usage
- 
Install the package via Composer: composer require illuminated/console-mutex
- 
Use Illuminated\Console\WithoutOverlappingtrait:use Illuminated\Console\WithoutOverlapping; class ExampleCommand extends Command { use WithoutOverlapping; // ... }
Strategies
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');
    }
    // ...
}
Advanced
Set custom timeout
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;
Handle multiple commands
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';
    }
    // ...
}
Set custom storage folder
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');
    }
    // ...
}
Troubleshooting
Trait included, but nothing happens?
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');
    }
    // ...
}
Several traits conflict?
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();
    }
    // ...
}
Sponsors
License
Laravel Console Mutex is open-sourced software licensed under the MIT license.



