Бо подію диспетчеризували всередині транзакції, а воркер узяв завдання раніше, ніж транзакція закомітилася.
DB::transaction(function () use ($data) {
$order = Order::create($data);
OrderPlaced::dispatch($order); // слухач у черзі вже може стартувати
$order->items()->createMany($data['items']);
});
Воркер читає замовлення з бази - а там його ще немає, або немає позицій. Якщо транзакція відкотиться, слухач узагалі обробить те, чого не існує.
Рішення:
ShouldQueueAfterCommitу слухачі - стати в чергу лише після коміту;ShouldDispatchAfterCommitу події - диспетчеризувати саму подію після коміту (не дістануть і синхронні слухачі);after_commit => trueу конфігурації підключення черги - для всіх завдань;- для спостерігачів -
ShouldHandleEventsAfterCommit.
Якщо транзакції немає, усе це спрацьовує одразу, тож поведінка поза транзакцією не змінюється.
Те саме стосується листів і сповіщень у черзі - у них є afterCommit().