Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як зробити завдання ідемпотентним?

Черги гарантують доставку «хоча б раз», а не «рівно раз»: завдання може виконатися повторно після таймауту, падіння воркера чи ручного queue:retry. Ідемпотентне завдання при повторі не робить шкоди - не списує гроші двічі й не шле другий лист.

Прийоми, від простого до надійного:

1. Перевірка стану перед дією:

public function handle(): void
{
    if ($this->order->paid_at !== null) {
        return;   // уже оброблено
    }
    // ...
}

Сама по собі має вікно гонки: два воркери можуть одночасно побачити «не оплачено».

2. Обмеження бази як гарантія. Унікальний індекс на payments.order_id перетворює другу вставку на помилку, а не на дубль. Перевірку в коді можна обійти, обмеження в базі - ні.

3. Ключ ідемпотентності для зовнішніх API. Платіжні сервіси приймають заголовок на кшталт Idempotency-Key: повторний запит з тим самим ключем поверне перший результат, а не створить новий платіж.

4. Поділ на кроки. Не «спиши кошти й надішли лист» в одному завданні, а запис наміру в базу, списання, і лист окремим завданням після успіху - щоб повтор листа не тягнув повтор списання.

Плюс afterCommit(), щоб завдання не стартувало раніше, ніж закомічено транзакцію, яка його породила.

Докладніше в документації: Робота з невдалими завданнями

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання