The Cache Was Working, But It Still Caused Duplicate API Calls
Кеш не був зламаний.
Проте три одночасні запити з одним і тим самим ім'ям користувача призвели до трьох окремих звернень до GitHub.
Це сталося в CommitPulse — API на базі Next.js, який перетворює дані GitHub на SVG-бейджи. Коли README стає вірусним, тисячі людей одночасно переглядають бейдж. Це створює величезне навантаження.
Кеш працював для послідовних запитів. Він не справлявся з одночасними.
Ось у чому проблема:
- Запит A перевіряє кеш. Промах кешу. Запит A починає отримання даних з GitHub.
- Запит B надходить через 5 мс. Він перевіряє кеш. Даних у кеші все ще немає, оскільки запит A ще не завершено. Запит B починає другий виклик.
- Запит C надходить через 10 мс. Він також бачить промах кешу і починає третій виклик.
Це проблема «громового стада» (thundering herd problem). Промах кешу під високим навантаженням спричиняє шквал ідентичних викликів до вашого апстрім-провайдера. Якщо ви використовуєте API з обмеженням частоти запитів, як-от GitHub, це може миттєво вичерпати ваші ліміти.
Рішенням є об'єднання запитів (request coalescing).
Ви повинні відстежувати незавершені запити окремо від завершених записів у кеші. Я впровадив Map для керування запитами, що перебувають у процесі виконання (in-flight):
- Коли запит починається, зберігайте його
PromiseуMap. - Якщо надходить другий запит із тим самим ключем, не починайте новий виклик.
- Замість цього поверніть існуючий
PromiseізMap. - Після завершення запиту видаліть його з
Mapі збережіть результат у кеш.
Це гарантує, що скільки б людей одночасно не запитували ті самі дані, до API звернеться лише один виклик.
Виправляючи це, я також усунув три інші помилки у граничних випадках у тому ж файлі:
- Помилки відсутності токена: система надсилала "undefined" як облікові дані. Я оновив код, щоб перевіряти токени перед виконанням запитів.
- Витоки пам'яті: логіка повторних спроб залишала застарілі слухачі подій на
AbortSignals. Я додав логіку очищення, щоб запобігти витокам. - URL-ін'єкції: імена користувачів зі спеціальними символами ламали шляхи API. Я додав кодування, щоб захистити структуру URL.
Кешу недостатньо. Вам також потрібно усувати дублювання запитів, які перебувають у процесі виконання.
Source: https://dev.to/eshaanagrawal/the-cache-was-working-and-still-causing-duplicate-api-calls-3n51
