neurohotep/console-mutex

Laravel 控制台命令的互斥锁。


README

Become a Patron

StyleCI Build Status Coverage Status

Latest Stable Version Latest Unstable Version Total Downloads License

Laravel 控制台命令的互斥锁。

Example

目录

使用方法

  1. 通过 Composer 安装包

    composer require illuminated/console-mutex
  2. 使用 Illuminated\Console\WithoutOverlapping 特质

    use Illuminated\Console\WithoutOverlapping;
    
    class ExampleCommand extends Command
    {
        use WithoutOverlapping;
    
        // ...
    }

策略

可以通过各种策略防止重叠

  • file(默认)
  • mysql
  • redis
  • memcached

对于小型应用程序,默认的 file 策略就足够好了,这些应用程序部署在单个服务器上。如果您的应用程序更加复杂且部署在多个节点上,那么您可能希望使用另一种互斥锁策略。

您可以通过指定 $mutexStrategy 字段来更改互斥锁策略

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    protected $mutexStrategy = 'mysql';

    // ...
}

或者通过使用 setMutexStrategy 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    public function __construct()
    {
        parent::__construct();

        $this->setMutexStrategy('mysql');
    }

    // ...
}

高级

设置自定义超时时间

默认情况下,互斥锁会检查是否有正在运行的命令,如果找到,则退出。但是,您可以手动设置互斥锁的超时时间,这样它就可以等待另一个命令执行完毕,而不是立即退出。

您可以通过指定 $mutexTimeout 字段来更改互斥锁超时时间

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    protected $mutexTimeout = 3000; // milliseconds

    // ...
}

或者通过使用 setMutexTimeout 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    public function __construct()
    {
        parent::__construct();

        $this->setMutexTimeout(3000); // milliseconds
    }

    // ...
}

$mutexTimeout 字段有三个可能的选项

  • 0 - 不等待检查(默认);
  • {milliseconds} - 检查,并等待最多指定的毫秒数;
  • null - 等待,直到正在运行的命令执行完毕;

处理多个命令

有时为多个命令设置公共互斥锁很有用。您可以通过设置它们相同的互斥锁名称轻松实现这一点。默认情况下,互斥锁名称基于命令的名称和参数生成。

要更改此设置,请覆盖您的命令中的 getMutexName 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    public function getMutexName()
    {
        return "icmutex-for-command1-and-command2";
    }

    // ...
}

自定义互斥文件存储

如果您使用的是 file 策略,互斥文件将默认存储在 storage/app 文件夹中。

您可以通过在您的命令中覆盖 getMutexFileStorage 方法来更改存储文件夹

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    public function getMutexFileStorage()
    {
        return storage_path('my/custom/path');
    }

    // ...
}

故障排除

包含特质,但没有发生任何事情?

注意,WithoutOverlapping 特质正在覆盖 initialize 方法

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

    // ...
}

如果您命令也覆盖了 initialize 方法,那么您应该自己调用 initializeMutex 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

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

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

    // ...
}

几个特质冲突?

如果您正在使用另一个 illuminated/console-% 包,那么您可能会遇到“特质冲突”。

例如,如果您正在尝试构建可记录命令,该命令受到重叠保护

class ExampleCommand extends Command
{
    use Loggable;
    use WithoutOverlapping;

    // ...
}

您将收到致命错误 - 特质冲突,因为这两个特质都覆盖了 initialize 方法

如果两个特质插入同名的方法,如果冲突没有明确解决,则会产生致命错误。

自己覆盖 initialize 方法,并按照所需顺序初始化特质

class ExampleCommand extends Command
{
    use Loggable;
    use WithoutOverlapping;

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

    // ...
}

许可协议

MIT 许可协议。请参阅许可文件以获取更多信息。

Support on Patreon