Очереди и задания
Отправка письма, обработка картинки, выгрузка отчёта занимают секунды. Если делать это во время запроса, пользователь всё это время смотрит на загрузку. Очередь откладывает работу: запрос отвечает сразу, а задание выполняется в фоне.
Как это работает
Приложение кладёт задание в очередь — таблицу в базе или Redis. Отдельный процесс, обработчик, постоянно забирает задания оттуда и выполняет. Где хранится очередь, задаёт переменная QUEUE_CONNECTION в .env.
Создание задания
php artisan make:job ProcessPhotoРабота описана в методе handle(), а данные передаются через конструктор:
namespace App\Jobs;
use App\Models\Photo;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class ProcessPhoto implements ShouldQueue
{
use Queueable;
public function __construct(public Photo $photo) {}
public function handle(): void
{
// уменьшить картинку, создать превью…
$this->photo->update(['processed' => true]);
}
}Интерфейс ShouldQueue и означает «выполнять в фоне».
Отправка в очередь
use App\Jobs\ProcessPhoto;
public function store(Request $request)
{
$photo = Photo::create([...]);
ProcessPhoto::dispatch($photo);
return back()->with('status', 'Фото загружено и обрабатывается');
}Ответ уходит пользователю сразу — обработка начнётся, когда до задания дойдёт очередь.
Отложенный запуск
ProcessPhoto::dispatch($photo)->delay(now()->addMinutes(5));
ProcessPhoto::dispatch($photo)->onQueue('images');onQueue() кладёт задание в отдельную очередь — так срочные задачи не ждут за медленными.
Запуск обработчика
Задания никто не выполнит, пока не запущен обработчик:
php artisan queue:workНа рабочем сервере этот процесс должен работать постоянно. За ним следит менеджер процессов — Supervisor или systemd: он перезапустит обработчик, если тот остановится.
Повторные попытки
Задание может упасть: недоступен почтовый сервер, оборвалась сеть. Число попыток и паузу между ними задают свойствами:
class ProcessPhoto implements ShouldQueue
{
use Queueable;
public int $tries = 3;
public int $backoff = 60;
public function failed(\Throwable $exception): void
{
// сообщить администратору
}
}Задания, исчерпавшие попытки, попадают в таблицу неудачных:
php artisan queue:failed
php artisan queue:retry allРазработка без обработчика
Значение QUEUE_CONNECTION=sync выполняет задания сразу, во время запроса. Это удобно для разработки и тестов, но не для рабочего сайта.
Частая ошибка
Обработчик загружает код один раз при запуске. После обновления сайта он продолжит выполнять задания старым кодом. При каждом размещении новой версии перезапускайте обработчики:
php artisan queue:restart