-2

Hi,

I have a job which process below operations:

  1. Import data, save in db
  2. Change status of saved records
  3. 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).

Himakar
  • 345
  • 4
  • 17
  • Does this answer your question? [Safely catch a 'Allowed memory size exhausted' error in PHP](https://stackoverflow.com/questions/8440439/safely-catch-a-allowed-memory-size-exhausted-error-in-php) – Arleigh Hix May 12 '21 at 21:10
  • If you run out of memory the PHP process will probably die and any opened transactions will be rolled back automatically. If the process does not die then that means you can `try...catch` the errors and rollback there – apokryfos May 12 '21 at 22:47
  • @apokryfos die will never caught, it is not an exception!! – Himakar May 13 '21 at 05:13
  • @Himakar yes but that will terminate the running script and opened transactions will be rolled back. – apokryfos May 13 '21 at 06:18
  • @apokryfos it rollbacks the transaction doesn't mean rollback the operations done in that process!! Transaction rollback means worker will re try that process, but the operations done in the failed process will be remain same! – Himakar May 13 '21 at 06:28
  • @ArleighHix thank you for the link, it gave me necessary information – Himakar May 13 '21 at 07:01

1 Answers1

0

Catching Fatal Errors

This gave me the necessary information.

If anyone would like to use transaction in Job handle and runs out of memory they can detect it my placing below code in the handle method.

error_reporting(-1);
            register_shutdown_function(function(){
                $error = error_get_last();
                if(null !== $error)
                {
                    echo 'Caught at shutdown';
                }
            });

Thank you @ArleighHix for providing the information in the comment.

Himakar
  • 345
  • 4
  • 17