Cache Berfungsi, Tetapi Ia Masih Menyebabkan Panggilan API Berulang
Cache tersebut tidak rosak.
Namun, tiga permintaan serentak untuk nama pengguna yang sama telah memanggil GitHub sebanyak tiga kali.
Ini berlaku dalam CommitPulse, sebuah API Next.js yang menukarkan data GitHub kepada lencana SVG. Apabila sebuah README menjadi tular, beribu-ribu orang akan melihat lencana tersebut pada masa yang sama. Ini mewujudkan trafik yang sangat besar.
Cache berfungsi untuk permintaan berturutan. Ia gagal untuk permintaan serentak.
Inilah masalahnya:
- Permintaan A menyemak cache. Ia adalah cache miss. Permintaan A mula mengambil data daripada GitHub.
- Permintaan B tiba 5ms kemudian. Ia menyemak cache. Ia masih merupakan cache miss kerana Permintaan A belum selesai. Permintaan B memulakan pengambilan data kedua.
- Permintaan C tiba 10ms kemudian. Ia juga melihat cache miss dan memulakan pengambilan data ketiga.
Ini adalah masalah thundering herd. Cache miss di bawah beban tinggi mencetuskan lambakan panggilan serupa kepada pembekal upstream anda. Jika anda menggunakan API yang mempunyai had kadar (rate-limited) seperti GitHub, ini boleh menghabiskan had anda dengan serta-merta.
Penyelesaiannya ialah request coalescing.
Anda mesti menjejaki permintaan yang sedang menunggu secara berasingan daripada entri cache yang telah selesai. Saya melaksanakan satu Map in-flight untuk menguruskan perkara ini:
- Apabila permintaan bermula, simpan
Promisetersebut di dalam satuMap. - Jika permintaan kedua tiba untuk kunci yang sama, jangan mulakan pengambilan data baharu.
- Sebaliknya, pulangkan
Promisesedia ada daripadaMaptersebut. - Sebaik sahaja permintaan selesai, buangkannya daripada
Mapdan simpan hasilnya ke dalam cache.
Ini memastikan tidak kira berapa ramai orang meminta data yang sama pada satu masa, hanya satu panggilan sahaja yang akan memanggil API tersebut.
Sambil membaiki perkara ini, saya juga menyelesaikan tiga pepijat kes terpinggir (edge-case) yang lain dalam fail yang sama:
- Ralat Token Hilang: Sistem menghantar "undefined" sebagai kredential. Saya telah mengemas kininya untuk mengesahkan token sebelum membuat permintaan.
- Kebocoran Memori (Memory Leaks): Logik cubaan semula (retry) meninggalkan pendengar acara (event listeners) yang usang pada
AbortSignals. Saya telah menambah logik pembersihan untuk mengelakkan kebocoran. - Suntikan URL (URL Injection): Nama pengguna dengan aksara khas merosakkan laluan API. Saya telah menambah pengekodan (encoding) untuk melindungi struktur URL.
Cache sahaja tidak mencukupi. Anda juga perlu menghapuskan duplikasi (deduplicate) terhadap permintaan yang sedang dalam proses (in flight).
Sumber: https://dev.to/eshaanagrawal/the-cache-was-working-and-still-causing-duplicate-api-calls-3n51
