oriceon/console-mutex

Laravel 控制台命令的互斥锁。为 Laravel 10.x 分支

11.0.0 2024-03-14 07:02 UTC

This package is auto-updated.

Last update: 2024-09-14 08:00:21 UTC


README

Mutex for Laravel Console Commands

Laravel 控制台互斥锁

这是从原始仓库分叉以支持 Laravel v10.x 的版本

Buy Me A Coffee

StyleCI Build Status codecov

Packagist Version Packagist Stars Packagist Downloads Packagist License

Laravel 控制台命令的互斥锁。

Laravel Console Mutex - Demo

目录

使用方法

  1. 通过 Composer 安装此包

    composer require srd2010/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 string $mutexStrategy = 'mysql';

    // ...
}

或使用 setMutexStrategy() 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

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

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

    // ...
}

高级

设置自定义超时

默认情况下,如果互斥锁看到该命令正在运行,它将立即退出。你可以通过设置超时来更改这种行为,在该超时期间互斥锁可以等待另一个正在运行的命令完成其执行。

你可以通过指定 $mutexTimeout 字段来设置超时

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    // In milliseconds
    protected ?int $mutexTimeout = 3000;

    // ...
}

或使用 setMutexTimeout() 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

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

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

    // ...
}

以下是 $mutexTimeout 字段的处理方式

  • 0 - 不等待(默认);
  • {int} - 等待指定的毫秒数;
  • null - 等待正在运行的命令完成其执行;

处理多个命令

有时可能需要为多个命令使用共享互斥锁。你可以通过为所有这些命令设置相同的互斥锁名称来轻松实现这一点。

你应该使用 getMutexName() 方法

class ExampleCommand extends Command
{
    use WithoutOverlapping;

    public function getMutexName()
    {
        return 'shared-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();

        parent::initialize($input, $output);
    }

    // ...
}

如果你的命令也覆盖了 initialize() 方法,你必须自己调用 initializeMutex() 方法

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');
    }

    // ...
}

有几个特性冲突?

如果你正在使用另一个 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)
    {
        // Initialize conflicting traits
        $this->initializeMutex();
        $this->initializeLogging();
    }

    // ...
}

原始赞助商

Laravel Idea
Material Theme UI Plugin

许可证

Laravel 控制台互斥锁是开源软件,许可协议为 MIT 协议