Laravel排队作业如何处理已删除的模型作为输入?

时间:2016-02-13 07:09:15

标签: laravel jobs laravel-5.2

如果将Laravel排队作业传递给Eloquent模型作为输入,但在队列中运行作业之前删除模型会发生什么?

例如,我正在使用Laravel 5.2构建电子商务网站,客户可以在其中输入地址和付款方式。付款方式属于地址。但是,如果客户试图删除地址,而不是级联并删除与其关联的任何付款方式,我会通过将其标记为已禁用来软删除该地址。这样,在客户更新与其关联的帐单邮寄地址之前,仍然可以使用付款方式。

但是,如果删除了付款方式并且它引用了已被软删除的地址,我想进行一些垃圾收集并从数据库中删除该地址。这不需要同步发生,因此我编写了一个简单的可排队作业来完成此任务。 handle方法如下所示:

public function handle(PaymentMethodRepository $paymentMethodRepository, AddressRepository $addressRepository)
{
    $billingAddress = $paymentMethodRepository->address($this->paymentMethod);

    if ( ! $billingAddress->enabled) {
        $addressRepository->delete($billingAddress);
    }
}

我在PaymentMethodsController的destroy方法中调度此作业。但是,如果在队列中执行作业之前从数据库中删除了传递给作业的付款方式,那么作业是否会失败?

我还在开发网站,所以我没有服务器来部署和测试会发生什么。我知道模型被序列化以放入队列中,但我想知道在恢复模型以执行作业时是否会出现问题。

1 个答案:

答案 0 :(得分:0)

是的,如果"序列化模型"在作业执行之前删除。该模型并未真正序列化 - 作业存储模型类和模型标识符,并在执行前获取模型。

要解决此问题,您可以将模型的主键存储在作业中,然后在执行作业时检查记录是否存在:

class DeleteAddressJob extends Job implements ShouldQueue
{
    private $addressId;

    public function __construct(int $addressId)
    {
        $this->addressId = $addressId;
    }

    public function handle(AddressRepository $addressRepository)
    {
        $address = $addressRepository->find($this->addressId);

        if (is_null($address)) {
            // Address doesn't exist. Complete job...
            return;
        }

        // Delete the address...
    }
}