Создание изолируемых команд в Laravel
Оглавление
- Создание изолируемой команды
- Выполнение изолируемой команды
- Примерный вариант использования
- Управление таймаутами блокировки
В Laravel 9.38 появилась концепция изолируемых команд (Isolatable commands) — консольных команд, которые не могут быть запущены, если уже запущен другой экземпляр команды. На этой неделе у меня наконец-то появилась возможность протестировать эту возможность, и она отлично работает!
Создание изолируемой команды
Чтобы воспользоваться этой функцией, необходимо запустить провайдер кэша. Кэш — это место, где Laravel хранит блокировку, сообщающую ему, что команда запущена. Вы можете использовать любой из следующих драйверов кэша: memcached
, redis
, dynamodb
, database
, file
или array
.
Вот пример команды. Единственное отличие этой команды от не изолируемой заключается в том, что к определению класса добавлено implements Isolatable
.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Isolatable;
class IsolatableCommand extends Command implements Isolatable
{
protected $signature = 'test:isolate';
protected $description = 'Example isolated command';
public function handle(): void
{
$this->info("Start");
sleep(10);
$this->info('End');
}
}
Выполнение изолируемой команды
Для запуска изолированной команды необходимо использовать флаг --isolated
.
php artisan test:isolate --isolated
Если команда не запущена в другом процессе, она будет запущена. Если команда уже запущена, вы получите сообщение об ошибке:
The [test:isolate] command is already running.
Примерный вариант использования изолируемой команды
В Laravel есть возможность использовать изолированные команды, например команду migrate
. Вы можете выполнить php artisan migrate --isolated
, чтобы быть уверенным, что миграция базы данных не будет выполняться более одного раза, если ваше приложение имеет более одного сервера в кластере.
Управление таймаутами блокировки изолируемой команды
По умолчанию блокировка снимается с изолируемых команд, как только команда завершает выполнение. Если команда прервана или не завершена, блокировка будет снята через 1 час.
Вы можете изменить это время, добавив функцию isolationLockExpiresAt
в класс команды. В приведённом примере, эта функция изменит срок действия блокировки с 1 часа на 5 минут:
public function isolationLockExpiresAt()
{
return now()->addMinutes(5);
}