Skip to content

Reset job attempts counter when retrying failed jobs via queue:retry.#192

Open
binzram wants to merge 2 commits intostackkit:masterfrom
binzram:feature/retry-reset
Open

Reset job attempts counter when retrying failed jobs via queue:retry.#192
binzram wants to merge 2 commits intostackkit:masterfrom
binzram:feature/retry-reset

Conversation

@binzram
Copy link

@binzram binzram commented Mar 14, 2026

Hey there

Just found this package yesterday, already migrated one app over and it's doing a wonderful job! ❤️ Thanks!

I ran into this behavior when artisan queue:retry is called: it reads the raw payload from failed_jobs and creates another task. The number of attempts is saved inside this payload (internal.attempts). The stored payload already has attempts at the maximum for the job, so the requeued task immediately throws MaxAttemptsExceededException on execution: Making queue:retry effectively "obsolete."

I found that pushRaw() is only called without $options['job'] in the retry case. So this is a bit of a wonky solution to tackle it, especially resetting it to zero... But thought why not share this :)

Cheers

@binzram
Copy link
Author

binzram commented Mar 14, 2026

class RetryFailedCloudTask extends Command
{
    protected $signature = 'cloudtasks:retry {id? : Failed job ID} {--all}';

    public function handle(): void
    {
        $query = DB::table('failed_jobs');

        if ($this->option('all')) {
            $jobs = $query->get();
        } else {
            $jobs = $query->where('id', $this->argument('id'))->get();
        }

        foreach ($jobs as $failed) {
            $payload = json_decode($failed->payload, true);
            // Reset attempts
            $payload['internal']['attempts'] = 0;

            app('queue')
                ->connection($failed->connection)
                ->pushRaw(json_encode($payload), $failed->queue);

            DB::table('failed_jobs')->where('id', $failed->id)->delete();

            $this->info("Retried job {$failed->id}: {$payload['displayName']}");
        }
    }
}

And my current workaround command.

@marickvantuil
Copy link
Member

Thanks for the PR!! It's very useful to have this fixed!

I have cleaned it up a little bit by resetting the attempts before the job is added to the failed table. That does mean that existing jobs in the table have to be corrected manually, but this way it keeps the package code a bit more straightforward. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants