Процесс queue:work может завершиться по девяти разным причинам, и до выхода Laravel 13.30 вывод в консоль выглядел одинаково для всех случаев. Воркер, работающий под управлением Supervisor, который перезапускается каждые несколько минут, мог превысить лимит памяти, потерять соединение с базой данных или получить команду queue:restart после деплоя. Чтобы отличить эти ситуации друг от друга, приходилось регистрировать слушатель событий или сопоставлять время перезапуска с логами деплоя.
Теперь команда выводит причину в своей последней строке:
2026-09-01 13:20:40 Worker STOPPED Memory limit exceeded
#Вывод в консоль и JSON
Класс WorkCommand регистрирует слушатель для события WorkerStopping рядом с уже существующими слушателями статуса задач и очередей, поэтому строка остановки выводится в тех же двух форматах, что и остальной вывод. При использовании флага --json она представляет собой запись наряду со строками по каждой задаче:
{"level":"info","status":"stopped","reason":"empty","exit_code":0,"jobs_processed":12,"memory":34.0,"timestamp":"2026-09-01T13:20:40.118273+00:00"}
Поле reason содержит строковое значение enum, которое удобно использовать для фильтрации. Поле memory указывает объем в мегабайтах, округленный до одного знака после запятой, или null , если воркер не зафиксировал этот показатель. Поле level принимает значение info при коде завершения 0 и warning во всех остальных случаях.
Эта строка не выводится при использовании флагов --quiet и --silent , а также если причина равна null. Если воркер был принудительно завершен извне (например, механизмом OOM killer или сигналом SIGKILL ), код, отправляющий событие, не успевает выполниться, поэтому такие завершения остаются незафиксированными в выводе.
#Причины остановки и коды завершения
WorkerStopReason — это уже существовавший ранее enum. Данное изменение добавило в него метод description() , благодаря чему в консоли и в любых ваших слушателях используются одинаковые строки:
| Значение | Описание | Код завершения |
|---|---|---|
empty |
Очередь пуста | 0 |
empty_for |
Очередь пуста в течение заданного времени | 0 |
max_jobs |
Превышено максимальное количество задач | 0 |
max_time |
Превышено максимальное время работы | 0 |
restart_signal |
Получен сигнал перезапуска | 0 |
interrupted |
Работа прервана | 0 |
lost_connection |
Соединение потеряно | 0 |
memory |
Превышен лимит памяти | 12 |
timed_out |
Таймаут задачи | 1 |
#Фильтрация JSON-вывода
Поскольку причина теперь является отдельным полем, найти её в логе можно с помощью простого фильтра:
php artisan queue:work --json --max-time=3600 2>&1 | \
jq -c 'select(.status == "stopped")'
Если менеджер процессов записывает вывод в файл, этот же запрос можно выполнить по логам постфактум.
#Событие WorkerStopping
Для любых задач, выходящих за рамки простого чтения вывода, по-прежнему лучше использовать событие. Оно передает причину остановки вместе со статусом завершения, количеством обработанных задач, временной меткой последней задачи и объемом памяти, использовавшимся на момент остановки воркера:
use Illuminate\Queue\Events\WorkerStopping;
Event::listen(function (WorkerStopping $event) {
Log::info('Worker stopped', [
'reason' => $event->reason?->value,
'status' => $event->status,
'jobs' => $event->jobsProcessed,
'memory' => $event->memoryUsage,
]);
});
Используйте его, чтобы подсчитывать количество остановок по причинам для дашборда или отправлять эти данные в систему сбора метрик.
Автор пулл-реквеста: Jack Bayliss в #61339.
Комментарии (0)
Пока нет комментариев — будьте первым.