关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题[已踩坑]

Laravel: 8.x
PHP: 7.3
OS: MAC

我现在有 job1 和job-batch 队列若干

job1有问题代码:

       Bus::batch($jobs)
            // 所有任务完成才执行的回调
            ->finally(function (Batch $batch) {

                if ($batch->finished()) {
                    dispatch(new BeforeLoanExportFinishJob($this->task->id));
                }

            })->dispatch();

job1正常代码:

$taskId = $this->task->id;

        Bus::batch($jobs)
            // 所有任务完成才执行的回调
            ->finally(function (Batch $batch) use ($taskId) {

                if ($batch->finished()) {
                    dispatch(new BeforeLoanExportFinishJob($taskId));
                }

            })->dispatch();

报错:
直接是 500 Server error ,502 bad way ,前面是服务器错误,后者大概率是内存过大,超时

根本原因来自 批次队列的 finally 回调内部调用了 $this 造成了内部循环引用,内存无法释放,这个位置大家一定要避坑,很难调试

下面放上这个issue地址:
Referencing $this within batch callback depletes memory

关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题

job1 使用了外部传入对象

/**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(Task $task)
    {
        //
        $this->task = $task;
    }

job1 内有调用了batch 队列, 再使用batch 队列回调的时候, 内部调用了this ,结果就是把外层的队列给序列化,提示的错误是pdo 无法支持序列化,就是因为再batch 的回调内使用了this

finally 回调里面如果是闭包,执行的是序列化的操作,会导致序列化失败

关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题

local.ERROR: You cannot serialize or unserialize PDO instances {"exception":"[object] (PDOException(code: 0): You cannot serialize or unserialize PDO instances at /Users/raybon/TaiFinance/www/download-center/vendor/opis/closure/src/SerializableClosure.php:155)
[stacktrace]

使用批次队列正确的方式:

关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题

后面使用过程中,切记 this 直接调用,会造成内存泄漏

8.x 版本 还没文档提示

关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题

9.x 版本已经更新了提示:

关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题

[9.x] Add note to ‘Chain Failures’ and ‘Queueing Closures’ section to not use ‘$this’ in callbacks

本作品采用《CC 协议》,转载必须注明作者和本文链接
每天一点小知识,到那都是大佬,哈哈
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!