It would be nice to have Retry All button
Feature request
This may relate to #310
Atm, a new job is created after failed retry. Ideally, after a failed retry, the original job should be deleted and a new job is created to prevent having duplicated jobs.
e.g. Job#1 failed, Job#2 (duplicate of job#1) is created, then retry Job#2 which fails again, Job#3 (duplicate of job#2) is created. Now I have Job#1, Job#2 and Job3# do the same thing. If "Retry All" would work, I would execute 3 jobs. The end goal is to have Job#3 exists, and Job#1 and Job#2 are removed
It would be nice to have Retry All button
Feature request
Yes, would be a nice addition.
In the past, I just opened my Chrome dev tools console and executed $('table i.icon').click();. Good enough for me.
I made a little endpoint which seems to do the trick:
Route::get('/retry-all', function () {
/** @var JobRepository $jobs */
$jobs = app(JobRepository::class);
return $jobs->getFailed()->map(function ($job) {
$id = $job->id;
dispatch(new RetryFailedJob($id));
return $id;
});
});
Hey all, we're gonna close this as Taylor has rejected this in the past. I don't think we'll re-consider this as we don't feel this is useful in a production environment. Sorry.
@driesvints What would you advice alternatively in a production environment?
The queue retry all command doesn't seem to use a cursor either so ends up getting killed if you have many jobs. It will also be great to be able to retry all the jobs on a particular connection.
For anyone interested, I created a model scaffold for FailedJobs table and ended up using something like this:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\FailedJob;
use Carbon\Carbon;
class FailedJobsCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'jobs:failed {connection?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Retry failed jobs';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
\ini_set('memory_limit', -1);
\set_time_limit(0);
$this->retryJobs();
}
public function retryJobs()
{
$total = 0;
$connection = $this->argument('connection') ?: null;
pcntl_async_signals(true);
pcntl_signal(SIGINT, function () use ($total) {
$this->info("$total jobs queued");
return;
});
pcntl_signal(SIGTERM, function () use ($total) {
$this->info("$total jobs queued");
return;
});
$time = null;
if (config('horizon.trim.failed')) {
$time = Carbon::now()->subMinutes(config('horizon.trim.failed'));
$this->info("Using failed after time: $time");
}
if ($connection) {
if ($time) {
$cursor = FailedJob::where('failed_at', '>=', (string)$time)->where('connection', $connection)->cursor();
} else {
$cursor = FailedJob::where('connection', $connection)->cursor();
}
} else {
if ($time) {
$cursor = FailedJob::where('failed_at', '>=', (string)$time)->cursor();
} else {
$cursor = FailedJob::cursor();
}
}
foreach ($cursor as $j) {
$total += 1;
$payload = json_decode($j->payload, true);
if (isset($payload['attempts'])) {
$payload['attempts'] = 0;
}
$j->payload = json_encode($payload);
$this->laravel['queue']->connection($j->connection)->pushRaw(
$j->payload, $j->queue
);
$this->info("Job {$j->id} successfully queued for retry");
}
$this->info("$total jobs successfully queued for retry");
}
}
@xwiz best to create something yourself like the above.
I'm just saying that the defaults currently available are not good/efficient for production use. But again I understand failed jobs can be dirty to test.
Most helpful comment
Yes, would be a nice addition.
In the past, I just opened my Chrome dev tools console and executed
$('table i.icon').click();. Good enough for me.