
Tidak semua job bakal berhasil. Email server bisa down, koneksi database bisa putus, API eksternal bisa timeout. Laravel sudah punya mekanisme bawaan untuk ini, dan teman-teman tinggal konfigurasi sesuai kebutuhan.
Pertama, setup tabel untuk menyimpan job yang gagal:
php artisan queue:failed-table
php artisan migrate
Lalu di dalam Job, teman-teman bisa konfigurasi perilaku retry:
<?php
namespace App\Jobs;
use Illuminate\Support\Facades\Log;
use Throwable;
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public $tries = 3;
public $backoff = [10, 60];
public function __construct(public User $user) {}
public function handle(): void
{
Mail::to($this->user)->send(new WelcomeMail());
}
public function failed(Throwable $exception): void
{
Log::error('SendWelcomeEmail gagal untuk user ' . $this->user->id, [
'error' => $exception->getMessage(),
]);
$this->user->notify(new JobFailed());
}
}
Dengan konfigurasi di atas, Laravel akan mencoba 3 kali. Percobaan pertama langsung, kedua tunggu 10 detik, ketiga tunggu 60 detik. Kalau tetap gagal, method failed() dipanggil dan job masuk ke tabel failed_jobs.
Kalau teman-teman ingin menggunakan batas waktu sebagai penentu retry (bukan jumlah percobaan), bisa pakai retryUntil:
use Carbon\Carbon;
public function retryUntil(): Carbon
{
return now()->addMinutes(30);
}
Untuk inspect dan manage failed jobs lewat Artisan:
php artisan queue:failed
php artisan queue:retry all
php artisan queue:retry 5
php artisan queue:forget 5
php artisan queue:flush
Satu tips tambahan: teman-teman bisa juga menggunakan $this->fail($exception) di dalam handle() untuk menandai job sebagai gagal secara manual, misalnya kalau dapat response error dari API eksternal meski tidak ada exception yang dilempar.