Pada banyak deployment Laravel, gejala paling umum adalah job berhasil masuk ke Redis tetapi statusnya tetap pending terus. Aplikasi terlihat normal, proses dispatch() tidak error, Redis bisa diakses, tetapi email tidak terkirim, sinkronisasi data tidak jalan, atau proses background lain tidak pernah selesai. Dalam praktik, masalah ini hampir selalu ada di jalur queue worker, bukan pada pemanggilan job-nya.
Artikel ini fokus pada studi kasus spesifik: Laravel menggunakan Redis sebagai queue backend dan Supervisor sebagai process manager di server Linux. Tujuannya bukan membahas teori queue dari nol, tetapi memberi urutan pengecekan yang langsung mengarah ke akar masalah.
Studi Kasus: Job Masuk Redis, Tapi Tidak Diproses
Misalkan aplikasi melakukan dispatch seperti ini:
ProcessOrder::dispatch($order);Tidak ada exception. Di Redis terlihat antrian bertambah. Namun proses tidak berjalan. Gejalanya biasanya salah satu dari berikut:
- Queue di Redis terus bertambah.
- Tidak ada log eksekusi dari job.
failed_jobskosong, padahal job tidak selesai.- Supervisor terlihat aktif, tetapi worker sebenarnya tidak menjalankan command yang benar.
- Worker sering restart karena timeout, permission, atau environment salah.
Masalah ini perlu dipisahkan menjadi tiga lapisan:
- Aplikasi Laravel: koneksi queue, nama queue, job timeout, tries.
- Redis: apakah job benar-benar masuk ke queue yang sesuai.
- Supervisor + worker: apakah proses
php artisan queue:workbenar-benar berjalan stabil.
1. Cek Hal Paling Dasar: QUEUE_CONNECTION dan Environment
Kesalahan paling sering adalah aplikasi menulis job ke koneksi tertentu, sementara worker membaca koneksi lain. Contoh paling umum: di .env aplikasi tertulis QUEUE_CONNECTION=redis, tetapi worker berjalan dengan environment lama atau config cache lama sehingga masih membaca sync, database, atau konfigurasi Redis yang berbeda.
Verifikasi konfigurasi aktif
php artisan env
php artisan tinkerLalu di Tinker:
config('queue.default');
config('database.redis.default.host');
config('queue.connections.redis.queue');Jika hasilnya tidak sesuai dengan .env, kemungkinan ada config cache yang belum diperbarui. Jalankan:
php artisan optimize:clear
php artisan config:clear
php artisan cache:clearJika server production memakai deployment script, pastikan perintah cache dijalankan ulang setelah perubahan environment.
Catatan: Worker Laravel adalah proses long-running. Jika
.envberubah, worker lama tidak otomatis membaca perubahan. Anda perlu me-restart worker, biasanya lewat Supervisor.
Cek queue name yang dipakai
Job bisa saja didispatch ke queue emails, sementara worker hanya mendengarkan queue default. Misalnya:
ProcessOrder::dispatch($order)->onQueue('high');Jika worker dijalankan tanpa --queue=high atau urutan queue yang benar, job akan tetap pending.
Contoh worker:
php artisan queue:work redis --queue=high,default --sleep=3 --tries=3 --timeout=902. Pastikan Worker Benar-Benar Jalan
Sering kali Supervisor statusnya running, tetapi command worker gagal, crash berulang, atau jalan dengan path PHP yang salah. Karena itu, jangan langsung percaya status service sebelum memeriksa proses dan log.
Perintah diagnosa penting
php artisan queue:work redis --once -v
php artisan queue:listen
php artisan queue:failed
php artisan queue:retry all
php artisan queue:flushYang paling berguna untuk diagnosa awal adalah:
php artisan queue:work redis --once -vJika command ini berhasil memproses satu job, berarti:
- Laravel bisa konek ke Redis.
- Job valid dan dapat dijalankan.
- Masalah besar kemungkinan ada di Supervisor atau worker daemon.
Selanjutnya cek proses di Linux:
ps aux | grep 'queue:work'
supervisorctl statusKalau tidak ada proses worker aktif, jelas job akan menumpuk. Kalau ada tetapi sering restart, lihat log Supervisor.
Cek log Laravel dan Supervisor
tail -f storage/logs/laravel.log
tail -f /var/log/supervisor/laravel-worker.log
tail -f /var/log/supervisor/laravel-worker-error.logDi sinilah sering ketahuan penyebab nyata: permission, binary PHP salah, folder aplikasi tidak ditemukan, atau worker mati karena exception fatal.
3. Contoh Konfigurasi Supervisor Minimal yang Benar
Berikut contoh konfigurasi minimal yang cukup aman untuk banyak kasus:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=/usr/bin/php /var/www/app/artisan queue:work redis --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=1
redirect_stderr=false
stdout_logfile=/var/log/supervisor/laravel-worker.log
stderr_logfile=/var/log/supervisor/laravel-worker-error.log
stopwaitsecs=3600
directory=/var/www/appSetelah membuat atau mengubah file config:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart laravel-worker:*Hal penting dari konfigurasi di atas
- command harus menunjuk ke path PHP dan path
artisanyang benar. - directory harus sesuai root project Laravel.
- user harus punya akses ke project,
storage, danbootstrap/cache. - stdout_logfile dan stderr_logfile harus bisa ditulis oleh Supervisor.
- autorestart=true penting agar worker hidup kembali jika crash.
Kesalahan kecil seperti path salah atau user salah cukup untuk membuat queue macet terus tanpa gejala yang jelas dari aplikasi.
4. Masalah Permission yang Sering Terlihat Sepele
Pada server Linux, permission adalah penyebab klasik queue tidak jalan stabil. Worker mungkin berhasil start, tetapi gagal menulis log, cache, atau file temporary, lalu mati diam-diam.
Folder yang wajib bisa diakses
storage/bootstrap/cache/- folder log Supervisor, misalnya
/var/log/supervisor/
Contoh perbaikan umum:
sudo chown -R www-data:www-data /var/www/app
sudo chown -R www-data:www-data /var/log/supervisor
sudo chmod -R 775 /var/www/app/storage /var/www/app/bootstrap/cacheSesuaikan user dengan user yang dipakai Supervisor. Jika Supervisor menjalankan worker sebagai www-data tetapi file dimiliki user deploy lain tanpa izin tulis, worker bisa gagal saat runtime.
5. Timeout, Tries, dan Kenapa Job Terlihat Pending atau Hilang
Job yang lama diproses bisa dianggap macet padahal sebenarnya worker terus membunuhnya karena timeout. Dalam kombinasi Redis + worker daemon, ini sering menimbulkan kebingungan: job tampak tidak selesai, kadang diproses ulang, kadang masuk gagal setelah beberapa percobaan.
Parameter yang perlu dipahami
- --timeout: batas waktu eksekusi satu job oleh worker.
- --tries: jumlah percobaan sebelum dipindah ke
failed_jobs. - retry_after: durasi job dianggap hilang lalu boleh diambil ulang.
Contoh worker:
php artisan queue:work redis --sleep=3 --tries=3 --timeout=120Jika job memang butuh waktu lama, jangan pakai timeout terlalu kecil. Tetapi jangan juga membesarkan timeout tanpa alasan, karena job yang benar-benar hang akan lebih lama terdeteksi.
Prinsip amannya:
timeoutdisesuaikan dengan durasi realistis job.triesjangan terlalu besar jika job tidak idempoten.- Pastikan job menangani exception dengan baik dan tidak loop tanpa akhir.
Cek failed jobs
Jangan berasumsi job pending jika sebenarnya sudah gagal.
php artisan queue:failedUntuk retry:
php artisan queue:retry allUntuk membersihkan:
php artisan queue:flushJika tabel failed_jobs belum ada, buat dulu migration-nya agar kegagalan bisa terlacak:
php artisan queue:failed-table
php artisan migrate6. Urutan Diagnosa Cepat yang Efektif
Kalau ingin langsung ke solusi, berikut urutan yang paling praktis saat queue Redis menumpuk:
- Cek koneksi queue aktif: pastikan
QUEUE_CONNECTION=redisbenar-benar terbaca. - Clear cache konfigurasi:
php artisan optimize:clear. - Jalankan manual satu job:
php artisan queue:work redis --once -v. - Cek status Supervisor:
supervisorctl status. - Lihat log Supervisor dan Laravel untuk error nyata.
- Verifikasi path command, user, dan directory di config Supervisor.
- Periksa permission untuk
storage,bootstrap/cache, dan file log. - Cek timeout, tries, dan failed_jobs.
- Restart worker setelah perubahan:
supervisorctl restart laravel-worker:*.
Dalam banyak kasus, akar masalah selesai di salah satu dari empat titik ini: config cache lama, worker tidak jalan, Supervisor salah command/path, atau permission log/storage.
7. Kesalahan Umum yang Sering Terjadi
- Supervisor menjalankan PHP versi berbeda dari yang dipakai aplikasi.
- Worker mendengarkan queue
default, padahal job dikirim ke queue lain. - Perubahan
.envdilakukan tanpa restart worker. - Redis konek dari web app, tetapi worker shell memakai environment berbeda.
- Job timeout sebelum selesai lalu terus di-retry.
failed_jobstidak disiapkan sehingga kegagalan tidak terlihat.
Penutup
Saat queue Laravel pending terus di Redis, fokuskan diagnosa pada jalur eksekusi worker, bukan hanya pada kode dispatch. Selama job bisa masuk ke Redis, masalah paling mungkin ada pada konfigurasi queue yang tidak sinkron, worker yang tidak aktif, Supervisor yang salah setup, permission server, atau parameter timeout/tries yang tidak cocok.
Pendekatan terbaik adalah memeriksa sistem secara berurutan: validasi environment, jalankan worker manual, baca log, lalu audit konfigurasi Supervisor. Dengan urutan ini, Anda biasanya bisa menemukan akar masalah dalam beberapa menit, bukan menebak-nebak dari sisi aplikasi.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!