Создание изолируемых команд в Laravel

Источник: «Creating Isolatable Commands in Laravel»
Как создать в 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);
}

Дополнительные материалы

Предыдущая Статья

История compact() и extract()

Следующая Статья

Игнорирование файлов в Git. Больше, чем просто .gitignore