ಕ್ಯಾಶ್ ಕೆಲಸ ಮಾಡುತ್ತಿತ್ತು, ಆದರೂ ಇದು ಡೂಪ್ಲಿಕೇಟ್ API ಕರೆಗಳಿಗೆ ಕಾರಣವಾಯಿತು
ಕ್ಯಾಶ್ ಕೆಟ್ಟು ಹೋಗಿರಲಿಲ್ಲ.
ಆದರೂ, ಒಂದೇ ಬಳಕೆದಾರ ಹೆಸರಿಗಾಗಿ (username) ಬಂದ ಮೂರು ಏಕಕಾಲಿಕ ವಿನಂತಿಗಳು (concurrent requests) GitHub ಅನ್ನು ಮೂರು ಬಾರಿ ತಲುಪಿದವು.
ಇದು CommitPulse ನಲ್ಲಿ ಸಂಭವಿಸಿತು, ಇದು GitHub ಡೇಟಾವನ್ನು SVG ಬ್ಯಾಡ್ಗಳಾಗಿ ಪರಿವರ್ತಿಸುವ ಒಂದು Next.js API ಆಗಿದೆ. ಒಂದು README ವೈರಲ್ ಆದಾಗ, ಸಾವಿರಾರು ಜನರು ಏಕಕಾಲದಲ್ಲಿ ಬ್ಯಾಡ್ ಅನ್ನು ನೋಡುತ್ತಾರೆ. ಇದು ಭಾರಿ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಸೃಷ್ಟಿಸುತ್ತದೆ.
ಕ್ಯಾಶ್ ಅನುಕ್ರಮ ವಿನಂತಿಗಳಿಗೆ (sequential requests) ಕೆಲಸ ಮಾಡಿತು. ಆದರೆ ಏಕಕಾಲಿಕ ವಿನಂತಿಗಳಿಗೆ ವಿಫಲವಾಯಿತು.
ಸಮಸ್ಯೆ ಇಲ್ಲಿದೆ:
- ವಿನಂತಿ A ಕ್ಯಾಶ್ ಅನ್ನು ಪರಿಶೀಲಿಸುತ್ತದೆ. ಅದು 'miss' ಆಗುತ್ತದೆ. ವಿನಂತಿ A GitHub ನಿಂದ ಡೇಟಾವನ್ನು ಪಡೆಯಲು ಪ್ರಾರಂಭಿಸುತ್ತದೆ.
- ವಿನಂತಿ B 5ms ನಂತರ ಬರುತ್ತದೆ. ಅದು ಕ್ಯಾಶ್ ಅನ್ನು ಪರಿಶೀಲಿಸುತ್ತದೆ. ವಿನಂತಿ A ಇನ್ನೂ ಪೂರ್ಣಗೊಂಡಿರುವುದಿಲ್ಲದ ಕಾರಣ, ಇದು ಕೂಡ 'miss' ಆಗುತ್ತದೆ. ವಿನಂತಿ B ಎರಡನೇ ಫೆಚ್ (fetch) ಅನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತದೆ.
- ವಿನಂತಿ C 10ms ನಂತರ ಬರುತ್ತದೆ. ಇದು ಕೂಡ ಕ್ಯಾಶ್ ಮಿಸ್ ಅನ್ನು ನೋಡಿ ಮೂರನೇ ಫೆಚ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತದೆ.
ಇದು 'thundering herd' ಸಮಸ್ಯೆ. ಹೆಚ್ಚಿನ ಲೋಡ್ ಅಡಿಯಲ್ಲಿ ಕ್ಯಾಶ್ ಮಿಸ್ ಆಗುವುದು ನಿಮ್ಮ ಅಪ್ಸ್ಟ್ರೀಮ್ ಪ್ರೊವೈಡರ್ಗೆ (upstream provider) ಒಂದೇ ರೀತಿಯ ಕರೆಗಳ ಪ್ರವಾಹವನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ. ನೀವು GitHub ನಂತಹ ರೇಟ್-ಲಿಮಿಟೆಡ್ (rate-limited) API ಅನ್ನು ಬಳಸುತ್ತಿದ್ದರೆ, ಇದು ನಿಮ್ಮ ಮಿತಿಗಳನ್ನು ತಕ್ಷಣವೇ ಖಾಲಿ ಮಾಡಬಹುದು.
ಇದಕ್ಕೆ ಪರಿಹಾರವೆಂದರೆ 'request coalescing'.
ನೀವು ಪೂರ್ಣಗೊಂಡ ಕ್ಯಾಶ್ ಎಂಟ್ರಿಗಳಿಂದ ಪ್ರತ್ಯೇಕವಾಗಿ ಬಾಕಿ ಇರುವ ವಿನಂತಿಗಳನ್ನು (pending requests) ಟ್ರ್ಯಾಕ್ ಮಾಡಬೇಕು. ಇದನ್ನು ನಿರ್ವಹಿಸಲು ನಾನು ಒಂದು in-flight Map ಅನ್ನು ಬಳಸಿದೆ:
- ವಿನಂತಿ ಪ್ರಾರಂಭವಾದಾಗ, ಅದರ
Promiseಅನ್ನುMapನಲ್ಲಿ ಸಂಗ್ರಹಿಸಿ. - ಅದೇ ಕೀ (key) ಗಾಗಿ ಎರಡನೇ ವಿನಂತಿ ಬಂದರೆ, ಹೊಸ ಫೆಚ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಬೇಡಿ.
- ಬದಲಾಗಿ,
Mapನಿಂದ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವPromiseಅನ್ನು ಹಿಂತಿರುಗಿಸಿ. - ವಿನಂತಿ ಪೂರ್ಣಗೊಂಡ ನಂತರ, ಅದನ್ನು
Mapನಿಂದ ತೆಗೆದುಹಾಕಿ ಮತ್ತು ಫಲಿತಾಂಶವನ್ನು ಕ್ಯಾಶ್ನಲ್ಲಿ ಉಳಿಸಿ.
ಇದು ಎಷ್ಟು ಜನರು ಏಕಕಾಲದಲ್ಲಿ ಒಂದೇ ಡೇಟಾವನ್ನು ವಿನಂತಿಸಿದರೂ, ಕೇವಲ ಒಂದು ಕರೆ ಮಾತ್ರ API ಅನ್ನು ತಲುಪುವಂತೆ ಖಚಿತಪಡಿಸುತ್ತದೆ.
ಇದನ್ನು ಸರಿಪಡಿಸುವಾಗ, ನಾನು ಅದೇ ಫೈಲ್ನಲ್ಲಿ ಇತರ ಮೂರು ಎಡ್ಜ್-ಕೇಸ್ (edge-case) ಬಗ್ಗಳನ್ನು ಸಹ ಪರಿಹರಿಸಿದೆ:
- Missing Token Errors: ಸಿಸ್ಟಮ್ ಕ್ರೆಡೆನ್ಶಿಯಲ್ ಆಗಿ "undefined" ಅನ್ನು ಕಳುಹಿಸುತ್ತಿತ್ತು. ವಿನಂತಿಗಳನ್ನು ಮಾಡುವ ಮೊದಲು ಟೋಕನ್ಗಳನ್ನು ವ್ಯಾಲಿಡೇಟ್ ಮಾಡಲು ನಾನು ಅದನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಿದೆ.
- Memory Leaks: Retry ಲಾಜಿಕ್
AbortSignalsಮೇಲೆ ಹಳೆಯ ಇವೆಂಟ್ ಲಿಸನರ್ಗಳನ್ನು (event listeners) ಬಿಟ್ಟು ಹೋಗುತ್ತಿತ್ತು. ಸೋರಿಕೆಯನ್ನು ತಡೆಯಲು ನಾನು ಕ್ಲೀನಪ್ ಲಾಜಿಕ್ ಅನ್ನು ಸೇರಿಸಿದೆ. - URL Injection: ವಿಶೇಷ ಅಕ್ಷರಗಳನ್ನು ಹೊಂದಿರುವ ಬಳಕೆದಾರರ ಹೆಸರುಗಳು API ಪಾತ್ಗಳನ್ನು (paths) ಹಾಳುಮಾಡುತ್ತಿದ್ದವು. URL ರಚನೆಯನ್ನು ರಕ್ಷಿಸಲು ನಾನು ಎನ್ಕೋಡಿಂಗ್ ಅನ್ನು ಸೇರಿಸಿದೆ.
ಕೇವಲ ಕ್ಯಾಶ್ ಸಾಕಾಗುವುದಿಲ್ಲ. ಪ್ರಸ್ತುತ ಚಾಲ್ತಿಯಲ್ಲಿರುವ (in flight) ವಿನಂತಿಗಳನ್ನು ನೀವು ಡ್ಯೂಪ್ಲಿಕೇಟ್ ಮಾಡದಂತೆ (deduplicate) ನೋಡಿಕೊಳ್ಳಬೇಕು.
ಮೂಲ: https://dev.to/eshaanagrawal/the-cache-was-working-and-still-causing-duplicate-api-calls-3n51
