Метод afterCommit
Метод afterCommit применяется к экземпляру класса PendingDispatch,
который возвращается при вызове функции dispatch. Он позволяет отложить
отправку задания в очередь до момента, пока все операции в текущей транзакции
базы данных будут успешно зафиксированы. Первым параметром метод принимает
булево значение true или false, определяющее, следует ли ожидать
завершения транзакции. По умолчанию передаётся true.
Это особенно полезно, когда задание должно обрабатывать данные, созданные или изменённые в рамках текущей транзакции. Если отправить задание до фиксации транзакции, оно может начать выполнение до того, как данные станут доступны, что приведёт к ошибкам или некорректной обработке.
Синтаксис
<?php
dispatch(new Job($data))->afterCommit($condition);
?>
Пример
Допустим, у нас есть задание SendWelcomeEmail, которое отправляет
приветственное письмо пользователю. Мы хотим, чтобы это задание было
отправлено в очередь только после того, как новый пользователь будет
успешно сохранён в базе данных:
<?php
namespace AppHttpControllers;
use AppJobsSendWelcomeEmail;
use AppModelsUser;
use IlluminateSupportFacadesDB;
class UserController extends Controller
{
public function store(Request $request)
{
DB::transaction(function () use ($request) {
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->save();
dispatch(new SendWelcomeEmail($user))->afterCommit();
});
return response()->json(['message' => 'User created']);
}
}
?>
Пример
Метод afterCommit можно отключить, передав false. Это может
понадобиться, если задание должно быть отправлено немедленно, даже если
оно находится внутри транзакции:
<?php
namespace AppHttpControllers;
use AppJobsProcessOrder;
use AppModelsOrder;
use IlluminateSupportFacadesDB;
class OrderController extends Controller
{
public function store(Request $request)
{
DB::transaction(function () use ($request) {
$order = new Order();
$order->product = $request->product;
$order->amount = $request->amount;
$order->save();
dispatch(new ProcessOrder($order))->afterCommit(false);
});
return response()->json(['message' => 'Order created']);
}
}
?>
В этом случае задание будет отправлено в очередь сразу, независимо от статуса транзакции.
Пример
Если задание необходимо отправить только при успешной фиксации транзакции,
но при этом внутри транзакции выполняются множественные операции,
то метод afterCommit гарантирует, что задание попадёт в очередь
только после завершения всех операций:
<?php
namespace AppHttpControllers;
use AppJobsUpdateProductCache;
use AppModelsProduct;
use IlluminateSupportFacadesDB;
class ProductController extends Controller
{
public function update(Request $request, $id)
{
DB::transaction(function () use ($request, $id) {
$product = Product::find($id);
$product->price = $request->price;
$product->stock = $request->stock;
$product->save();
$log = new ActivityLog();
$log->action = 'Product updated';
$log->product_id = $product->id;
$log->save();
dispatch(new UpdateProductCache($product))->afterCommit();
});
return response()->json(['message' => 'Product updated']);
}
}
?>
Задание UpdateProductCache будет отправлено в очередь только после
того, как продукт обновлён и запись в лог добавлена.
Смотрите также
-
интерфейс
ShouldDispatchAfterCommit,
который позволяет указать поведение через атрибуты класса -
метод
delay,
который позволяет отложить выполнение задания -
метод
onQueue,
который указывает очередь для задания -
функция
dispatch,
которая отправляет задание в очередь