Hi,
I have a job which process below operations:
- Import data, save in db
- Change status of saved records
- Dispatch event with saved records for further operations.
At point 2. queue process runs out of memory and get killed. So I want to use a transaction here so that if point 2 not executed completely I want to rollback point 1 operation.
Currently I am doing this:
public function handle()
{
$model->beginTransaction();
$importer->import($model); // operation 1
$convertedItem = $service->digitize($model); // operation 2
$bill = $service->linkBill($convertedItem); // operation 3
$model->commit();
$dispatcher->dispatch(new Event($model, $convertedItem, $bill)); // dispatching event
}
/**
* Handling Failure exception
*
* @param \Throwable $exception
*/
public function failed(\Throwable $exception)
{
Log::error('Exception at job failure : {exception}', [
'exception' => $exception->getMessage()
]);
}
If no memory leak then everything works fine, if memory leak happened at operation 2 then I will not know it and can not rollback the model ($model->rollback()).
How to achieve this? Currently it is just leaving transactions open as they are not committed and not rolled back when memory leak happened.
PLEASE don't suggest to increase php memory limit
In job we can not catch the fatal error, the process will die there itself. Laravel queue listener has method to identify when run out of memory but it wont throw any specific exception or doesn't fire event.
There is an event fired when worker process killed (this is what happens when run out of memory) but it can not be used inside job like we use failed event. If we can access the event when worker process killed then it is easy to remove write locks on the model (basically its rollback).