Junior: питання на співбесіді з теми «Черги»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
3 питання
Черга дозволяє відкласти повільну роботу: замість того щоб виконувати її під час запиту й тримати користувача, застосунок ставить завдання в чергу й одразу повертає відповідь. Окремий процес - воркер - виконує її згодом.
Створити завдання:
php artisan make:job SendWelcomeEmail
class SendWelcomeEmail implements ShouldQueue
{
use Queueable;
public function __construct(public User $user)
{
}
public function handle(): void
{
Mail::to($this->user)->send(new WelcomeMail($this->user));
}
}
Інтерфейс ShouldQueue - це і є те, що відправляє завдання в чергу, а не виконує одразу.
Поставити в чергу:
SendWelcomeEmail::dispatch($user);
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(10));
Запустити воркер:
php artisan queue:work
Що варто виносити: надсилання листів і сповіщень, обробку зображень і відео, звернення до зовнішніх API, генерацію звітів та експорт, імпорт великих файлів - усе, що займає більше частки секунди й не потрібне для формування відповіді.
Що виносити не варто: те, результат чого користувач має побачити просто зараз. Черга - асинхронна, і відповідь її не дочекається.
Головна пастка новачка: у завдання передається модель, а Laravel серіалізує лише її ключ і перечитує запис у воркері. Якщо між постановкою й виконанням запис видалили, завдання впаде. Тому в чергу передають ідентифікатори або готові дані, а не громіздкі обʼєкти.
dispatch() ставить завдання в чергу: запит закінчується одразу, а роботу пізніше виконає воркер. dispatchSync() виконує handle() тут і зараз, у поточному процесі, черга не задіяна.
SendWelcomeEmail::dispatch($user); // у чергу - відповідь не чекає листа
SendWelcomeEmail::dispatchSync($user); // одразу - запит чекає, поки лист піде
Коли що:
dispatch()- для всього, що може зачекати й не потрібне користувачу в цій відповіді: листи, обробка зображень, звернення до зовнішніх API.dispatchSync()- у консольних командах і сідерах, де черга нічого не дає, і коли результат потрібен негайно.
Важливо: якщо клас не реалізує ShouldQueue, навіть dispatch() виконає його одразу. А в Laravel 13 є ще проміжний варіант - підключення deferred: завдання виконається в тому самому процесі, але після відправки відповіді користувачу, без воркера.
Найчастіше - бо ніхто їх не виконує. Черга лише зберігає завдання; виконує їх окремий процес-воркер:
php artisan queue:work
У свіжому застосунку Laravel підключення за замовчуванням - database (QUEUE_CONNECTION=database), тож завдання просто накопичуються в таблиці jobs, доки воркер не запущено.
Що ще перевірити:
- Інша черга. Завдання з
->onQueue('emails')не візьме воркер, що слухає лишеdefault: потрібен--queue=emails,default. - Інше підключення. Код пише в
redis, а воркер слухаєdatabase. - Старий код.
queue:workтримає застосунок у пам'яті й не бачить змін, доки його не перезапустити (php artisan queue:restart).
На сервері воркер має працювати постійно, тож його запускають під Supervisor чи systemd, які піднімуть процес після падіння. Для розробки є queue:listen: він повільніший, зате перечитує код на кожне завдання.