关于批次队列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 协议》,转载必须注明作者和本文链接
每天一点小知识,到那都是大佬,哈哈
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。