Пауза всех очередей Laravel во время деплоя

Во время большинства деплоев есть промежуток, когда код на диске уже изменился, а запущенные queue worker'ы еще не были перезапущены. Если в этот момент worker забирает задачу из очереди, он десериализует payload, созданный старой версией приложения, и пытается выполнить его с новым кодом. Обычно это не вызывает проблем, но переименованный класс задачи или изменившаяся сигнатура конструктора могут привести к ошибке и появлению failed job, которую затем придется запускать повторно вручную.

Обычно для решения этой проблемы используют maintenance mode, но он отключает гораздо больше, чем только очереди. Другой вариант — queue:restart, однако это лишь запрос на перезапуск: worker увидит его только между выполнением задач. В Laravel 13.25 появился третий вариант: глобальная пауза очередей, которая останавливает получение новых задач всеми worker'ами на всех соединениях, не затрагивая HTTP-трафик приложения.

Команда

Чтобы поставить на паузу все очереди, достаточно выполнить:

php artisan queue:pause --all

После завершения деплоя очереди можно возобновить:

php artisan queue:resume --all

Аргумент очереди для этих команд теперь необязателен. Флаг --all позволяет не указывать отдельную пару connection:queue. Без этого флага команды продолжают работать как раньше, принимая, например, redis:default.

Та же возможность доступна через фасад Queue. Это удобно для PHP-скриптов деплоя или контроллера административной панели:

use Illuminate\Support\Facades\Queue;

Queue::pauseAll();

// ...

Queue::resumeAll();

Глобальная пауза появилась в Laravel 13.25.0, выпущенном 11 августа 2026 года.

Что происходит при паузе

Поставленная на паузу очередь запрещает worker'ам забирать новые задачи. Сам процесс worker при этом продолжает работать и выполнять свой цикл, но вместо получения новой задачи переходит в режим ожидания.

Задача, которая уже выполняется в момент установки паузы, продолжит работу до завершения. Поэтому команда queue:pause --all не прерывает задачи посреди выполнения.

Производители задач также продолжают работать. Вызов SomeJob::dispatch() по-прежнему записывает задачи в Redis или базу данных. Эти задачи останутся в очереди до тех пор, пока пауза не будет снята.

На уровне реализации Laravel использует один cache key:

illuminate:queues:paused

Он записывается через forever(). Worker'ы и без этого регулярно обращаются к кэшу, проверяя состояние перезапуска и пауз отдельных очередей. Глобальный ключ проверяется в том же вызове many(), поэтому глобальная пауза не добавляет отдельных сетевых запросов к кэшу.

Методы QueueManager::isPaused() и getPausedQueues() считают очередь приостановленной, если установлен либо глобальный флаг, либо флаг конкретной очереди.

Глобальная и индивидуальная пауза независимы

pause() и pauseAll() используют разные ключи и намеренно не знают о состоянии друг друга. Например, очередь можно сначала поставить на индивидуальную паузу:

Queue::pause('redis', 'imports'); // очередь остановлена для проверки проблемной задачи

Queue::pauseAll();                // начинается деплой

Queue::resumeAll();               // деплой завершен

Queue::isPaused('redis', 'imports'); // true

После resumeAll() очередь redis:imports все равно останется на паузе.

Это позволяет безопасно использовать глобальную паузу в скриптах деплоя. Если кто-то намеренно остановил очередь imports еще до начала деплоя, команда resumeAll() не должна автоматически отменять это решение.

Чтобы снять индивидуальную паузу, по-прежнему используется отдельная команда:

php artisan queue:resume redis:imports

Глобальная команда resumeAll() снимает только глобальный флаг.

События

Для глобальной паузы Laravel добавляет два события — QueuesPaused и QueuesResumed. Они работают вместе с существующими событиями QueuePaused и QueueResumed, которые относятся к отдельным очередям.

Например, событие глобальной паузы можно использовать для логирования:

use Illuminate\Queue\Events\QueuesPaused;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;

Event::listen(function (QueuesPaused $event) {
    Log::warning('All queues paused');
});

Таким образом, приложение может зафиксировать момент, когда все очереди были остановлены во время деплоя.

Ключевая особенность новой возможности Laravel 13.25 заключается в том, что для остановки всех worker'ов больше не требуется перечислять каждую пару соединения и очереди. Достаточно queue:pause --all, а после завершения работ просто выполнить queue:resume --all.

Похожие статьи

Рекомендательные технологии Подробнее
Разработка и инструменты 5 месяцев назад

Laravel-Zipstream: потоковая генерация ZIP-архивов без нагрузки на сервер

Обзор пакета laravel-zipstream для потоковой генерации ZIP-архивов в Laravel. Разбираем, как работает стриминг, его преимущества и когда его стоит использовать.

Разработка и инструменты 7 месяцев назад

Laravel 12.44: добавлены HTTP-клиентские callbacks после получения ответа

Обзор релиза Laravel 12.44: добавлен метод afterResponse() для HTTP-клиента, новые методы для тестов и улучшенная валидация дат. Поясняется, как использовать новые фичи на практике.

Разработка и инструменты 6 месяцев назад

SSH проброс портов: руководство с примерами

Подробное руководство по пробросу портов через SSH. Разбираем локальный, удалённый и динамический режимы с примерами подключения к базе данных, веб-серверу и настройкой SOCKS-прокси.