CodeIgniter 4 cache lock job queue worker bisa diatasi dengan pola konsistensi antara cache status dan antrean pekerjaan: worker harus membaca status cache sebelum mengeksekusi job, menulis hasilnya saat selesai, dan membersihkan cache setelah job sukses. Pendekatan ini menghindarkan duplikasi eksekusi ketika worker restart atau job dikirim ulang.

Artikel ini membahas langkah teknis: sinkronisasi cache hasil job dengan status queue, penggunaan Redis/CacheHandler untuk koordinasi worker, strategi lock berbasis cache untuk race condition, penanganan retry/idempotency, serta metrik observasi yang relevan.

1. Menjaga konsistensi cache dan queue

Dalam sistem job queue, cache bisa menyimpan hasil terakhir atau status eksekusi untuk mencegah worker menjalankan job yang sama berulang. Pola yang aman adalah menulis status pending di cache saat job muncul, lalu saat worker mengambil job, ia memeriksa status cache tersebut.

Jika cache menyatakan job masih in-progress, worker lain bisa melewati job tersebut atau menunggu timeout. Setelah worker selesai, hasil atau flag completed diupdate, dan cache diberi TTL yang masuk akal agar tidak menjadi stale. Versi cache handler CodeIgniter 4 mendukung TTL dan penghapusan eksplisit melalui layanan Cache.

2. Koordinasi worker dengan Redis/Cache handler

Redis menjadi pilihan utama saat dibutuhkan operasi atomic dan konsistensi tinggi. Gunakan Redis sebagai CacheHandler di konfigurasi app/Config/Cache.php agar fungsi get(), set(), dan delete() memanfaatkan persistence dan response cepat.

Worker queue harus menulis metadata berikut dalam cache:

  • ID job
  • Status (pending, processing, completed, failed)
  • Timestamp
  • Nama worker atau host

Contoh implementasi dengan Redis CLI:

SETEX job:42:status 120 processing

Pada saat worker selesai, gunakan DEL job:42:status atau SET job:42:status completed dengan TTL untuk menandakan job selesai. Kombinasikan juga dengan queue payload yang menyertakan timestamp cache untuk deteksi retry.

3. Strategi lock berbasis cache untuk menghindari race

Lock memastikan hanya satu worker yang mengerjakan job tertentu. Implementasi sederhana menggunakan SET job:42:lock worker-A NX EX 60, yang hanya berhasil jika key belum ada. Jika operasi gagal, worker lain dapat menunggu beberapa saat sebelum mencoba lagi.

Contoh snippet PHP di CodeIgniter 4:

$cache = \Config\Services::cache();
$lockKey = "job:{$jobId}:lock";
$locked = $cache->save($lockKey, $workerId, 60, ['nx' => true]);
if (! $locked) {
    // tunggu atau skip
    return;
}
try {
    // eksekusi job
} finally {
    $cache->delete($lockKey);
}

Cache handler harus mendukung opsi nx (set if not exists). Jika tidak tersedia, wrapper Redis langsung bisa digunakan. Kunci lock harus memiliki expiration agar tidak mengunci forever jika worker crash.

Perlu trade-off: TTL terlalu pendek bisa menyebabkan job dikerjakan berulang jika eksekusi lambat, sedangkan TTL terlalu panjang bisa menyebabkan job tidak pernah dijalankan lagi setelah worker mati. Biasakan refresh lock secara berkala selama pekerjaan panjang.

4. Retry dan idempotency job

Cache membantu mendeteksi retry dengan menyimpan fingerprint job. Pastikan payload job memiliki ID unik yang digunakan dalam cache key untuk hasil atau status terbaru. Saat job dijalankan ulang, worker mengecek cache; jika status sudah completed, cukup abaikan dan laporkan sukses.

Selain itu, implementasikan idempotent handler dengan menyimpan state terakhir yang telah diproses. Misalnya, jika job memproses transaksi, simpan job:123:result dan verifikasi sebelum menulis perubahan permanen.

Gunakan queue retry policy yang mendukung backoff agar tidak langsung memicu job yang sama saat masih berpotensi menyebabkan race. Cache bisa mencatat jumlah retry dan waktu timeout untuk menentukan kapan job layak dicoba kembali.

5. Observability dan monitoring operasional

Tanpa observasi, strategi cache & lock sulit di-debug. Siapkan metrik berikut:

  • Jumlah job sementara dalam status in-progress menurut cache
  • Hit rate cache untuk status job
  • Jumlah lock timeout atau kegagalan complete
  • Durasi rata-rata job per worker

Gunakan logging terstruktur di worker untuk setiap perubahan status cache atau kegagalan lock. Integrasi dengan monitoring seperti Prometheus/Grafana atau Datadog memungkinkan visualisasi peringatan ketika lock menumpuk atau TTL tidak pernah berakhir.

Untuk debugging, periksa secara langsung key Redis yang terkait job, dan pastikan worker menyertakan identifier dalam log ketika mendapatkan atau melepaskan lock.

Kesimpulan

Pola konsistensi antara Redis cache dan job queue memastikan job tidak dieksekusi ganda, sementara strategi lock membantu menghindari race condition. Tambahkan handling retry/idempotent serta monitoring untuk mendeteksi kemacetan dan lock yang tidak pernah dilepas. Pendekatan ini membuat worker CodeIgniter 4 lebih andal dalam lingkungan produksi ramai.