Cache Berfungsi, Namun Tetap Menyebabkan Panggilan API Ganda
Cache tidak rusak.
Namun, tiga permintaan konkuren untuk nama pengguna yang sama memicu tiga panggilan ke GitHub.
Hal ini terjadi di CommitPulse, sebuah API Next.js yang mengubah data GitHub menjadi lencana SVG. Saat sebuah README menjadi viral, ribuan orang melihat lencana tersebut secara bersamaan. Hal ini menciptakan trafik yang masif.
Cache berfungsi untuk permintaan sekuensial. Namun, ia gagal untuk permintaan konkuren.
Inilah masalahnya:
- Permintaan A memeriksa cache. Terjadi cache miss. Permintaan A mulai mengambil data dari GitHub.
- Permintaan B tiba 5ms kemudian. Ia memeriksa cache. Hasilnya masih cache miss karena Permintaan A belum selesai. Permintaan B memulai pengambilan data kedua.
- Permintaan C tiba 10ms kemudian. Ia juga mendapati cache miss dan memulai pengambilan data ketiga.
Ini adalah masalah thundering herd. Cache miss di bawah beban tinggi memicu banjir panggilan identik ke penyedia upstream Anda. Jika Anda menggunakan API dengan pembatasan laju (rate-limited) seperti GitHub, hal ini dapat menghabiskan kuota Anda secara instan.
Solusinya adalah request coalescing.
Anda harus melacak permintaan yang tertunda secara terpisah dari entri cache yang sudah selesai. Saya mengimplementasikan sebuah Map in-flight untuk mengelola hal ini:
- Saat sebuah permintaan dimulai, simpan
Promise-nya ke dalam sebuahMap. - Jika permintaan kedua datang untuk kunci yang sama, jangan mulai pengambilan data baru.
- Sebaliknya, kembalikan
Promiseyang sudah ada dariMaptersebut. - Setelah permintaan selesai, hapus dari
Mapdan simpan hasilnya ke dalam cache.
Ini memastikan bahwa tidak peduli berapa banyak orang yang meminta data yang sama secara bersamaan, hanya satu panggilan yang akan memukul API.
Sambil memperbaiki hal ini, saya juga menyelesaikan tiga bug edge-case lainnya di file yang sama:
- Kesalahan Token Hilang: Sistem mengirimkan "undefined" sebagai kredensial. Saya memperbaruinya untuk memvalidasi token sebelum melakukan permintaan.
- Kebocoran Memori (Memory Leaks): Logika retry meninggalkan event listener usang pada
AbortSignals. Saya menambahkan logika pembersihan untuk mencegah kebocoran. - Injeksi URL: Nama pengguna dengan karakter khusus merusak jalur API. Saya menambahkan pengodean (encoding) untuk melindungi struktur URL.
Cache saja tidak cukup. Anda juga perlu melakukan deduplikasi pada permintaan yang sedang berjalan (in flight).
Sumber: https://dev.to/eshaanagrawal/the-cache-was-working-and-still-causing-duplicate-api-calls-3n51
