Skip to content

dmitry-ivanov/laravel-console-mutex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Laravel console mutex

StyleCI SensioLabsInsight

Prevents overlapping for Laravel console commands.

Dependencies

  • PHP >=5.5.9
  • Laravel >=5.2

Usage

  1. Install package through composer:

    composer require illuminated/console-mutex
  2. Use Illuminated\Console\WithoutOverlapping trait in your console command class:

    namespace App\Console\Commands;
    
    use Illuminate\Console\Command;
    use Illuminated\Console\WithoutOverlapping;
    
    class Foo extends Command
    {
        use WithoutOverlapping;
    
        // ...
    }
  3. Now your command is protected against overlapping:

    ➜ php artisan foo:bar baz
    Command is running now!

Strategies

Overlapping can be prevented by various strategies:

  • file (default)
  • mysql
  • redis
  • memcached

Default file strategy is fine for a small applications, which are deployed on a single server. If your application is more complex and, for example, is deployed on a several nodes, then you probably would like to use some other mutex strategy.

You can change mutex strategy by specifying $mutexStrategy field:

class Foo extends Command
{
    use WithoutOverlapping;

    protected $mutexStrategy = 'mysql';

    // ...
}

Or by using setMutexStrategy method:

class Foo extends Command
{
    use WithoutOverlapping;

    public function __construct()
    {
        parent::__construct();
    
        $this->setMutexStrategy('mysql');
    }

    // ...
}

Advanced

Sometimes it is useful to set common mutex for a several commands. You can easily achieve this by setting them the same mutex name. By default, mutex name is generated based on a command's name and arguments. To change this, just override getMutexName method in your command:

class Foo extends Command
{
    use WithoutOverlapping;

    public function getMutexName()
    {
        return "icmutex-custom-name";
    }

    // ...
}

Troubleshooting

Trait included, but nothing happens?

Note, that WithoutOverlapping trait is overriding initialize method:

trait WithoutOverlapping
{
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->initializeMutex();
    }

    // ...
}

If your command is overriding initialize method too, then you should call initializeMutex method by yourself:

class Foo extends Command
{
    use WithoutOverlapping;

    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->initializeMutex();

        $this->bar = $this->argument('bar');
        $this->baz = $this->argument('baz');
    }

    // ...
}

Several traits conflict?

If you're using some other cool illuminated/console-% packages, well, then you can find yourself getting "traits conflict". For example, if you're trying to build loggable command, which is protected against overlapping:

class Foo extends Command
{
    use Loggable;
    use WithoutOverlapping;

    // ...
}

You'll get fatal error, the "traits conflict", because both of these traits are overriding initialize method:

If two traits insert a method with the same name, a fatal error is produced, if the conflict is not explicitly resolved.

But don't worry, solution is very simple. Just override initialize method by yourself, and initialize traits in required order:

class Foo extends Command
{
    use Loggable;
    use WithoutOverlapping;

    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->initializeMutex();
        $this->initializeLogging();
    }

    // ...
}