Якщо ви користуєтесь чергами в Laravel, то скоріш за все зустрічались з помилкою Job has timed out при обробці завдань в черзі. Цю помилку можна побачити в таблиці failed_jobs після того як завдання завершилось з помилкою. Таке може трапитись коли завдання виконується довше 60 секунд і це означає що його обробка була зупинена.
За замовчуванням у різних версіях Laravel завдання поміщенні в чергу можуть виконуватись не довше 30 або 60 секунд. Але часто необхідно щоб завдання могли виконуватись значно довше. У цій статті я покажу як вирішити цю проблему декількома способами.
Що це за помлика?
Зверніть увагу, що ліміт встановлений в файлі php.ini для скріптів, які виконуються у терміналі не застосовується. Навіть якщо ви змінете значення в php.ini, всеодно омеження не буде застосоване. Ви можете впевниитись у цьому за допомогою команди:
php -i | grep "max_execution_time"

Назалежно від вибранного значення буде виведено 0. Але у Laravel є таймаут за замовчуванням для завдань які виконуються в черзі і він становить 60 секунд. Його можна перевірити в конструкторі класу Illuminate/Queue/WorkerOptions.

Якщо зараз створити клас завдання, яке виконується довше 60 секунд, та відправити його в чергу, то після 60 секунд обробки завдання буде позначенне проваленим, а в таблиці failed_jobs зявиться запис чому:
app/Jobs/SomeJob.php<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SomeJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
$i = 0;
$secondsToWait = 70;
$start = hrtime()[0];
while (hrtime()[0] - $start < $secondsToWait) {
$i++;
}
}
}
php artisan app:push-some-job-to-queue
php artisan queue:work

Як і очікувалось, після 60 секунд виконання, завдання буде помічене як провалене, і про це зявиться запис в таблиці failed_jobs:

Якщо ви хочете збільшити таймаут, це можна зробити двома способами. Додати поле у класс завдання, а бо ж використати опцію –timeout для команди обробки черги.
Як виправити цю помилку в Laravel
Клас завдання
Ви можете додати поле $timeout в клас завдання. Просто додайте його після інших полей перед конструктором.
app/Jobs/SomeJob.phppublic $timeout = 0;

Після цього ви можете знову додати ваше завдання в чергу, перезапустити команду обробки черги і все виконається успішно.

Команда обробки
Якщо ви не хочете модифікувати код програми, ви можете встановити таймаут глобально для команди обробки завдань черги. Для цього використовуйте опцію –timeout зі значенням 0:
php artisan queue:work --timeout 0

Така команда також буде обробляти завдання без обмежень по часу.
php artisan app:push-some-job-to-queue
php artisan queue:work
Висновки
У цій статті ми розглянули як виправити помилку Job Timed Out у Laravel. Це досить просто і зазвичай достатньо правильно налаштувати команди обробки і вам не потрібно буде думати про те що це налаштування треба додати у кожен клас черги.