-2

你好,

我有一份工作,处理以下操作:

  1. 导入数据,保存在db
  2. 更改已保存记录的状态
  3. 带有已保存记录的调度事件以进行进一步操作。

在第 2 点,队列进程耗尽内存并被杀死。所以我想在这里使用一个事务,这样如果第 2 点没有完全执行,我想回滚第 1 点操作。

目前我正在这样做:

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()
        ]);
    }

如果没有内存泄漏,那么一切正常,如果内存泄漏发生在操作 2,那么我将不知道它并且无法回滚模型($model->rollback())。

如何做到这一点?目前它只是让事务保持打开状态,因为它们在发生内存泄漏时没有提交并且没有回滚。

请不要建议增加 php 内存限制

在工作中我们无法捕捉到致命错误,进程将在那里自行死亡。Laravel 队列侦听器具有识别内存何时耗尽的方法,但它不会抛出任何特定异常或不触发事件。

当工作进程终止时会触发一个事件(这是内存不足时发生的情况),但它不能像我们使用失败事件一样在作业内部使用。如果我们可以在工作进程终止时访问该事件,那么很容易删除模型上的写锁(基本上是它的回滚)。

4

1 回答 1

0

捕捉致命错误

这给了我必要的信息。

如果有人想在作业句柄中使用事务并且内存不足,他们可以检测到我将其放置在句柄方法中的代码下方。

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

感谢@ArleighHix 在评论中提供信息。

于 2021-05-13T07:06:39.740 回答