Skip to content

[BUG] [5.5] artisan queue:retry failing when FETCH MODE is ASSOC. #23040

@rk

Description

@rk
  • Laravel Version: 5.5.33
  • PHP Version: 7.0.27
  • Database Driver & Version: MySQL 5.5

Description:

Because the application was recently upgraded to Laravel 5.5, I haven't had time to switch to FETCH_OBJ. I had to use the FETCH_ASSOC for compatibility until I get the time to rewrite a few hundred lines of code.

The job queue cannot be retried because:

In RetryCommand.php line 70:

  [ErrorException]
  Trying to get property of non-object

Steps To Reproduce:

You must switch the PDOStatement fetch mode to FETCH_ASSOC.

// From App\EventServiceProvider::boot
Event::listen(\Illuminate\Database\Events\StatementPrepared::class, function ($event) {
  $event->statement->setFetchMode(\PDO::FETCH_ASSOC);
});

Architect a job that purposefully throws an exception, and queue it.

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class TestFailureJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        throw new \RuntimeException("This job is meant to fail.");
    }
}

I queue it via php artisan tinker, myself:

~/path/to/project $ artisan tinker
Psy Shell v0.8.17 (PHP 7.0.27 — cli) by Justin Hileman
>>> \App\Jobs\TestFailureJob::dispatch()->delay(now()->addSeconds(10))
=> Illuminate\Foundation\Bus\PendingDispatch {#1055}

Run the job so it lands in the failed_jobs table, and then retry it...

php artisan queue:work --tries=1
php artisan queue:retry all

💥 💥 💥

In RetryCommand.php line 70:

  [ErrorException]
  Trying to get property of non-object

Mitigation

Here's how I'm mitigating the issue: by checking if the failed_jobs or jobs tables are being selected from.

Event::listen(\Illuminate\Database\Events\StatementPrepared::class, function ($event) {
  /** @var \PDOStatement $stmt */
  $stmt = $event->statement;

  if (!preg_match('/ FROM `?(failed_jobs|jobs)`?/i', $stmt->queryString)) {
    $stmt->setFetchMode(\PDO::FETCH_ASSOC);
  }
});

Long-term, a patch to fix the RetryCommand would be better than this regex test. I thought I saw something about this on laravel/internals a little while ago, but I can't find it now.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions