Как задание Laravel в очереди обрабатывает удаленную модель как ввод?

Что произойдет, если задание Laravel в очереди передается модели Eloquent в качестве входных данных, но модель удаляется до запуска задания в очереди?

Например, я создаю сайт электронной коммерции с Laravel 5.2, где клиент может вводить адреса и способы оплаты. Способ оплаты принадлежит адресу. Но если клиент пытается удалить адрес, а не каскадно и не удаляет любые способы оплаты, связанные с ним, я мягко удаляю адрес, помечая его как отключенный. Таким образом, способ оплаты может использоваться до тех пор, пока клиент не обновит адрес выставления счета, связанный с ним.

Однако, если метод оплаты удален и он ссылается на адрес, который был удален программным способом, я хочу выполнить сборку мусора и удалить адрес из базы данных. Это не должно происходить синхронно, поэтому я написал простую очередь для достижения этой цели. Метод handle выглядит следующим образом:

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

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

Я отправляю эту работу в destroy метод PaymentMethodsController. Однако если способ оплаты, переданный заданию, будет удален из базы данных до того, как задание будет выполнено в очереди, произойдет ли сбой задания?

Я все еще разрабатываю сайт, поэтому у меня нет сервера для развертывания и тестирования того, что происходит. Я знаю, что модель сериализуется для помещения в очередь, но мне интересно, возникнет ли проблема при восстановлении модели для выполнения задания.

1 ответ

Да, задание не будет выполнено, если "сериализованная модель" будет удалена перед выполнением задания. Модель на самом деле не сериализована - задание сохраняет класс модели и идентификатор модели и извлекает модель перед выполнением.

Чтобы обойти это, вы можете сохранить первичный ключ модели в задании, а затем при выполнении задания проверить, существует ли запись:

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...
    }
}
Другие вопросы по тегам