Queue dan Job: Kerja di Background
Pindahkan kerja berat ke background dengan job, driver database/redis, dan handling gagal.
Kenapa butuh queue?
Kirim email, resize gambar, hit API pihak ketiga, atau generate laporan: semua ini lambat kalau dikerjakan saat user menunggu response. Queue memindahkan kerja itu ke background, response kembali dalam milidetik.
Membuat dan menjalankan job
php artisan make:job KirimEmailSelamatDatang// app/Jobs/KirimEmailSelamatDatang.php
namespace App\Jobs;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class KirimEmailSelamatDatang implements ShouldQueue
{
use Queueable;
public function __construct(public User $user) {}
public function handle(): void
{
// kerja berat di sini, misal kirim email
Mail::to($this->user->email)->send(new SelamatDatang($this->user));
}
}
// Dispatch dari controller: langsung kembali, tidak menunggu
KirimEmailSelamatDatang::dispatch($user);
// Atau tunda 10 menit
KirimEmailSelamatDatang::dispatch($user)->delay(now()->addMinutes(10));Driver queue
# .env
QUEUE_CONNECTION=databaseDriver sync (default) menjalankan job langsung, cocok untuk development tapi tidak ada efek background. Driver database menyimpan job di tabel jobs (buat tabelnya dengan php artisan queue:table lalu migrate). Untuk production serius pakai redis.
Jalankan worker yang memproses antrean:
php artisan queue:workDi production, worker harus jalan terus via Supervisor atau systemd, bukan manual di terminal.
Job gagal dan retry
class KirimEmailSelamatDatang implements ShouldQueue
{
public int $tries = 3; // coba maksimal 3x
public int $backoff = 60; // jeda 60 detik antar percobaan
public function failed(\Throwable $e): void
{
// catat ke log atau beri tahu admin
Log::error('Job gagal: '.$e->getMessage());
}
}Job yang gagal total masuk ke tabel failed_jobs. Coba lagi dengan php artisan queue:retry all atau hapus dengan queue:flush.
Catatan teknis: Jangan dispatch job yang membawa model dengan relasi yang belum di-load lalu mengaksesnya di
handle()tanpa me-load ulang. Model di-serialize ulang saat job dijalankan worker, dan state relasinya tidak ikut. Pola aman: kirim ID saja, lalu query ulang di dalamhandle().