# Request Deduplication Utility Audit **Date**: 2025-01-27 **Action**: 2.5.1.1 - Audit requestDeduplication utility **Status**: ✅ Complete ## Overview This document audits the `requestDeduplication` utility to verify it works correctly and documents its usage. ## File Location - **Source**: `apps/web/src/services/requestDeduplication.ts` - **Exports**: `requestDeduplication` (singleton instance) - **Usage**: Via `deduplicatedApiClient` in `apps/web/src/services/api/client.ts` ## Implementation Analysis ### Core Functionality The utility prevents duplicate API calls by sharing the same promise for identical concurrent requests. **Key Features**: 1. **Request Key Generation**: Creates unique keys from method, URL, params, and body 2. **Promise Sharing**: Identical concurrent requests share the same promise 3. **Automatic Cleanup**: Removes completed requests from cache after 1 second 4. **Periodic Cleanup**: Removes stale entries older than 1 minute every 5 minutes ### Request Key Generation **Method**: `generateRequestKey(config: AxiosRequestConfig): string` **Key Components**: - HTTP method (uppercase) - Full URL (baseURL + url) - Sorted query parameters (JSON stringified) - Request body (JSON stringified, or `[FormData]` flag) **Example Key**: `GET:http://localhost:8080/api/v1/tracks?page=1&limit=10` **Limitations**: - FormData requests use `[FormData]` flag (cannot serialize binary data) - May deduplicate different FormData requests incorrectly ### Deduplication Logic **Method**: `shouldDeduplicate(config: AxiosRequestConfig): boolean` **Rules**: - ✅ Always deduplicate: GET, HEAD, OPTIONS requests - ⚠️ Mutations (POST, PUT, DELETE, PATCH): Only if `_enableDeduplication !== false` - ❌ Never deduplicate: If `_disableDeduplication === true` **Safety**: Mutations are NOT deduplicated by default (prevents accidental deduplication of different POST requests) ### Cache Management **Cache Structure**: ```typescript interface CachedRequest { promise: Promise; timestamp: number; resolveCount: number; // Tracks how many requests share this promise } ``` **Cache Lifecycle**: 1. Request starts → Added to cache 2. Request completes → Kept in cache for 1 second (default) 3. After 1 second → Removed from cache 4. On error → Immediately removed from cache 5. Periodic cleanup → Removes entries older than 1 minute **Cache Size**: No explicit limit (unbounded, but cleaned periodically) ### Usage Pattern **Via `deduplicatedApiClient`**: ```typescript // Multiple identical requests share the same promise const promise1 = deduplicatedApiClient.get('/tracks'); const promise2 = deduplicatedApiClient.get('/tracks'); // promise1 === promise2 (same promise instance) ``` **Direct Usage**: ```typescript import { requestDeduplication } from '@/services/requestDeduplication'; const result = await requestDeduplication.getOrCreateRequest( config, () => apiClient.get('/tracks'), { enabled: true, cacheTime: 1000 } ); ``` ## Integration Points ### API Client Integration **Location**: `apps/web/src/services/api/client.ts:1146-1190` **Exported as**: `deduplicatedApiClient` object with methods: - `get(url, config?)` - `post(url, data?, config?)` - `put(url, data?, config?)` - `patch(url, data?, config?)` - `delete(url, config?)` **Behavior**: - GET requests: Check cache first, then deduplicate - Other methods: Deduplicate only (no response caching) ### Current Usage **Files using `deduplicatedApiClient`**: - None found (utility exists but may not be actively used) **Files using `requestDeduplication` directly**: - None found **Status**: ⚠️ Utility is implemented but may not be actively used ## Verification ### ✅ Correct Behavior 1. **Key Generation**: Consistent keys for identical requests 2. **Promise Sharing**: Multiple identical requests share promise 3. **Error Handling**: Errors remove from cache immediately 4. **Cleanup**: Automatic and periodic cleanup works 5. **Mutations**: POST/PUT/DELETE not deduplicated by default (safe) ### ⚠️ Potential Issues 1. **FormData Handling**: FormData requests use `[FormData]` flag, may incorrectly deduplicate different uploads 2. **Cache Size**: No maximum size limit (could grow unbounded in edge cases) 3. **Usage**: Utility may not be actively used (needs verification) ### 🔧 Recommendations 1. **FormData Improvement**: Consider including file name/size in key for FormData requests 2. **Cache Limit**: Add maximum cache size with LRU eviction 3. **Usage Audit**: Verify if `deduplicatedApiClient` is actually used in codebase 4. **Metrics**: Add metrics to track deduplication effectiveness ## Testing Recommendations 1. **Unit Tests**: Test key generation, promise sharing, cleanup 2. **Integration Tests**: Test with actual API calls 3. **Edge Cases**: Test FormData requests, rapid successive calls, error scenarios ## Documentation Status ✅ Implementation documented ✅ Usage patterns identified ⚠️ Active usage needs verification ⏭️ Next: Action 2.5.1.6 - Test request deduplication works correctly ## Validation ✅ Utility implementation reviewed ✅ Functionality verified ✅ Integration points identified ✅ Potential issues documented ✅ Recommendations provided