Laravel 13.31 menambahkan job yang dapat diinterupsi, memungkinkan worker antrean menangkap sinyal SIGTERM yang dikirim selama deployment dan berhenti secara bersih alih-alih menghentikan tugas di tengah jalan. Tim yang menjalankan job berdurasi lama—memproses puluhan ribu baris, mengirim email massal, atau menghasilkan laporan—akan mendapat manfaat karena data tetap konsisten saat rilis baru diluncurkan.
Mengapa deployment sering menghentikan job secara paksa
Saat versi baru tiba, pengelola proses seperti Supervisor, Docker, dan Kubernetes memerintahkan worker yang ada untuk berhenti dengan mengirimkan SIGTERM, sebuah permintaan sopan untuk mengakhiri proses. Sebagian besar worker menunggu job saat ini selesai sebelum keluar. Masalah muncul ketika pengelola hanya memberikan waktu beberapa detik untuk mematuhinya. Jika sebuah job membutuhkan waktu beberapa menit, pengelola akan beralih ke SIGKILL, yang menghentikan proses secara instan. Job tersebut tidak pernah mencapai status yang konsisten, meninggalkan rekaman yang diperbarui sebagian, file yang tidak terhubung, atau pekerjaan duplikat.
Jawaban Laravel: interupsi kooperatif
Laravel 13.31 memperkenalkan kontrak bernama Interruptible yang dapat diimplementasikan oleh kelas job agar dapat menyadari adanya permintaan penghentian. Saat SIGTERM tiba, Laravel memanggil metode interrupted() pada job tersebut. Framework tidak menghentikan job secara otomatis; job tersebut harus memeriksa flag yang disetel oleh Laravel dan berhenti dengan sendirinya. Model kooperatif ini memungkinkan pengembang untuk menyelesaikan iterasi loop saat ini, membatalkan (roll back) perubahan parsial, atau menulis checkpoint sebelum keluar.
Cara membuat job dapat diinterupsi
- Implementasikan kontrak – tambahkan
implements Interruptibleke dalam definisi kelas job. - Periksa flag di dalam loop kerja – masukkan pemeriksaan di setiap iterasi untuk melihat apakah job harus berhenti.
- Lakukan pembersihan – di dalam
interrupted(), simpan status apa pun yang memungkinkan job untuk dilanjutkan nanti, atau catat interupsi tersebut untuk analisis di kemudian hari.
Jebakan terbesar: jangan gunakan --once
Menjalankan worker antrean dengan php artisan queue:work --once menonaktifkan penanganan sinyal sepenuhnya. Worker memproses satu job lalu keluar, tetapi ia tidak pernah mendaftarkan handler SIGTERM. Akibatnya, job apa pun yang dapat diinterupsi akan mengabaikan permintaan penghentian dan dibunuh di tengah proses. Pola ini sering muncul pada kontainer berbasis cron dan deployment satu kali (one-shot). Perbaiki dengan menjalankan mode daemon (php artisan queue:work) kapan pun Anda membutuhkan job yang dapat diinterupsi.
Memantau interupsi
Laravel memicu dua event yang dapat Anda gunakan (hook):
- WorkerInterrupted – dikeluarkan setiap kali worker mana pun menerima SIGTERM. Mencatat event ini memberikan pandangan tingkat tinggi tentang seberapa sering deployment menginterupsi worker.
- JobInterrupted – dikeluarkan hanya jika job saat ini mengimplementasikan kontrak Interruptible. Gunakan event ini untuk memicu pembersihan khusus job, seperti menghapus file sementara atau memperbarui penanda "baris terakhir yang diproses".
Mendengarkan event ini memungkinkan tim membangun dashboard yang menunjukkan dampak deployment dan mendeteksi job yang sering terhenti di tengah jalan.
Pelaporan ukuran antrean mendapat penyesuaian
Rilis ini menambahkan metode totalSize() ke pengelola antrean, yang mengembalikan jumlah total job yang tertunda di semua antrean. Nilai ini dapat diandalkan untuk driver berbasis database dan Redis, yang melaporkan jumlah aktual. Driver seperti SQS, Sync, dan Beanstalkd tetap mengembalikan angka nol karena mereka tidak menampilkan jumlah melalui API Laravel. Tim yang menggunakan SQS harus tetap mengandalkan metrik CloudWatch untuk kedalaman antrean.
Apa artinya bagi berbagai pengaturan
- Docker/Kubernetes – periode shutdown yang anggun (graceful shutdown) kini dapat digunakan secara efektif. Perpanjang periode grace termination agar job memiliki waktu beberapa detik untuk menyadari flag dan keluar dengan bersih.
- Supervisor – atur
stopwaitsecslebih tinggi dari waktu yang Anda perkirakan dibutuhkan job untuk selesai setelah menerima flag interupsi. - Job lama (legacy) – tinjau job apa pun yang berjalan lebih lama dari timeout pengelola dan, jika memungkinkan, buatlah menjadi dapat diinterupsi.
Sisi lain: kompleksitas tambahan
Fitur ini tidak menggantikan konfigurasi timeout yang tepat. Jika loop sebuah job tidak pernah memeriksa flag interupsi, pengelola akan tetap mengirimkan SIGKILL. Tim harus mengaudit jalur kode yang berjalan lama dan menyisipkan pemeriksaan pada titik henti (breakpoint) yang logis. Beberapa pengembang mungkin merasa boilerplate tambahan—mengimplementasikan kontrak dan menambahkan pemeriksaan flag—kurang menarik untuk job singkat yang sudah selesai dalam jendela waktu shutdown.
Daftar tindakan
- Pindai skrip deployment untuk flag
--oncedan ganti dengan mode daemon di mana job yang dapat diinterupsi digunakan. - Identifikasi job dengan durasi terlama (yang menyentuh puluhan ribu baris atau berjalan selama beberapa menit) dan tambahkan contract Interruptible.
- Sisipkan pemeriksaan flag di dalam setiap iterasi loop, dan pindahkan kode finalisasi yang diperlukan ke dalam metode
interrupted(). - Hubungkan listener ke
WorkerInterrupteddanJobInterrupteduntuk mengumpulkan metrik tentang seberapa sering deployment memengaruhi pemrosesan. - Untuk antrean Redis atau database, gunakan
totalSize()untuk memantau backlog; untuk SQS, tetap gunakan alarm CloudWatch yang ada.
Perlakukan penghentian yang dipicu oleh deployment sebagai langkah yang terkoordinasi, bukan penghentian mendadak. Laravel 13.31 menjaga konsistensi data dan meringankan kerumitan operasional akibat job yang setengah selesai. Kompensasinya adalah sedikit peningkatan tanggung jawab pada kode, tetapi tim yang mengandalkan pemrosesan latar belakang yang berat akan mendapatkan lingkungan produksi yang lebih andal.
