Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Очереди и задания

Отправка письма, обработка картинки, выгрузка отчёта занимают секунды. Если делать это во время запроса, пользователь всё это время смотрит на загрузку. Очередь откладывает работу: запрос отвечает сразу, а задание выполняется в фоне.

Как это работает

Приложение кладёт задание в очередь — таблицу в базе или 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

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.