Під час більшості деплоїв виникає «сліпа зона»: код на диску вже оновився, а воркери ще працюють за старими правилами. Якщо воркер бере завдання в цей проміжок часу, він десеріалізує payload, створений старим кодом, і намагається виконати його в новому середовищі. Зазвичай це призводить до помилок через перейменування класів або зміну конструкторів, що змушує розробників виправляти черги вручну.
Стандартні рішення мають свої мінуси: maintenance mode зупиняє весь додаток, а команда queue:restart є радше проханням, ніж гарантією, оскільки воркер бачить її лише між завданнями. Laravel 13.25 пропонує третій варіант: перемикач, що миттєво забороняє всім воркерам на всіх з’єднаннях брати нову роботу, не зачіпаючи HTTP-трафік.
# Команда
php artisan queue:pause --all
Для відновлення роботи:
php artisan queue:resume --all
Аргумент черги в обох командах тепер необов'язковий, тому достатньо передати лише прапор --all. Без нього команди працюють як раніше, приймаючи пару connection:queue.
Цей же функціонал доступний через фасад Queue для скриптів деплою на PHP або адміністративних панелей:
use Illuminate\Support\Facades\Queue;
Queue::pauseAll();
// ...
Queue::resumeAll();
# Як працює пауза
Коли чергу поставлено на паузу, воркери перестають брати нові завдання. Процес воркера залишається активним і продовжує цикл, але замість виконання завдань він переходить у режим очікування (sleep). Завдання, які вже виконуються в момент паузи, будуть завершені без перебоїв. На відправників (producers) це також не впливає: SomeJob::dispatch() продовжує записувати дані в Redis або базу даних — завдання просто чекатимуть відновлення роботи.
Технічно це реалізовано через ключ у кеші — illuminate:queues:paused, який записується методом forever(). Воркери перевіряють цей ключ у кожному циклі разом із сигналами перезапуску. Оскільки глобальний ключ отримується через той самий виклик many(), це не створює додаткового навантаження на мережу. Методи QueueManager::isPaused() та getPausedQueues() повідомляють, що чергу зупинено, якщо встановлено або глобальний ключ, або ключ конкретної черги.
# Незалежність перемикачів
Методи pause() та pauseAll() використовують різні ключі кешу і не залежать один від одного. Якщо чергу було зупинено індивідуально, команда resumeAll() залишить її на паузі:
Queue::pause('redis', 'imports'); // зупинили специфічну чергу для перевірки
Queue::pauseAll(); // початок деплою
Queue::resumeAll(); // завершення деплою
Queue::isPaused('redis', 'imports'); // true
Це логічна поведінка для деплой-скриптів. Якщо хтось свідомо зупинив чергу imports годину тому, загальний деплой не повинен її випадково активувати. Для розблокування конкретної черги, як і раніше, потрібна команда queue:resume redis:imports.
# Події (Events)
Разом зі стандартними подіями QueuePaused та QueueResumed (для окремих черг), тепер спрацьовують глобальні події:
use Illuminate\Queue\Events\QueuesPaused;
use Illuminate\Queue\Events\QueuesResumed;
Event::listen(function (QueuesPaused $event) {
Log::warning('Усі черги зупинено');
});
# Що ще почитати
- Пауза черги на певну кількість секунд у Laravel 12 — про метод
pauseFor()для тимчасової зупинки. - Методи інспекції черг у Laravel 13.8.0 — як переглянути завдання, що очікують у черзі.
- Laravel Jobs and Queue 101 — основи роботи зі з’єднаннями та іменованими чергами.
- Pause All Queues та новий Artisan dev UI у Laravel 13.25 — повний список оновлень релізу.
- Глобальний перемикач паузи реалізував Jack Bayliss у PR #61126.