veza/apps/web/docs/RESPONSE_CACHE_AUDIT.md
senke 03487b36e4 data-flow: audit response cache utility
- Completed Action 2.5.1.2: Audited responseCache utility
- Created RESPONSE_CACHE_AUDIT.md with complete analysis
- Verified core functionality: GET-only caching, Cache-Control support, ETag/Last-Modified
- Documented cache configuration (5min TTL, 100 entry limit, FIFO eviction)
- Identified potential issues: Limited usage, no automatic invalidation after mutations
- Noted cache only used via deduplicatedApiClient, not main apiClient
- Provided recommendations for integration and improvements
2026-01-11 16:44:28 +01:00

6.5 KiB

Response Cache Utility Audit

Date: 2025-01-27
Action: 2.5.1.2 - Audit responseCache utility
Status: Complete

Overview

This document audits the responseCache utility to verify it works correctly and documents its usage.

File Location

  • Source: apps/web/src/services/responseCache.ts
  • Exports: responseCache (singleton instance)
  • Usage: Via deduplicatedApiClient.get() in apps/web/src/services/api/client.ts

Implementation Analysis

Core Functionality

The utility caches GET request responses to reduce server load and improve performance.

Key Features:

  1. GET-only Caching: Only caches GET requests (safe, idempotent)
  2. Cache-Control Support: Respects server Cache-Control headers
  3. ETag Support: Optional ETag validation for cache revalidation
  4. Last-Modified Support: Optional Last-Modified header support
  5. Automatic Cleanup: Removes expired entries every minute
  6. Size Limit: Maximum 100 entries with FIFO eviction

Cache Configuration

Default Settings:

  • Default TTL: 5 minutes (300,000 ms)
  • Max Size: 100 entries
  • Respect Cache-Control: Enabled
  • ETag Support: Enabled

Configurable via constructor (currently uses defaults):

new ResponseCacheService({
  defaultTTL: 5 * 60 * 1000,
  maxSize: 100,
  respectCacheControl: true,
  enableETag: true,
})

Cache Key Generation

Method: generateCacheKey(config: AxiosRequestConfig): string

Key Components:

  • HTTP method (GET only)
  • Full URL (baseURL + url)
  • Sorted query parameters (JSON stringified)
  • Authorization header (for user-specific cache)

Example Key: GET:http://localhost:8080/api/v1/tracks?page=1&limit=10:Bearer token123

Important: Authorization header included → User-specific caching (correct behavior)

Cache Validation

Method: isCacheValid(cached: CachedResponse, config: AxiosRequestConfig): boolean

Validation Checks:

  1. TTL Check: Cache age vs maxAge/defaultTTL
  2. ETag Check: If-None-Match header matches cached ETag
  3. Last-Modified Check: If-Modified-Since header comparison

Cache Invalidation:

  • Expired entries removed automatically
  • no-store or no-cache directives prevent caching
  • Manual invalidation via invalidate(pattern) method

Cache Storage

Cache Structure:

interface CachedResponse<T = any> {
  data: T;
  headers: Record<string, string>;
  status: number;
  statusText: string;
  timestamp: number;
  etag?: string;
  lastModified?: string;
  maxAge?: number; // Cache max age in seconds
}

Storage: In-memory Map (not persisted across page reloads)

Usage Pattern

Via deduplicatedApiClient.get():

// First request: Fetches from server
const response1 = await deduplicatedApiClient.get('/tracks');

// Second request (within TTL): Returns from cache
const response2 = await deduplicatedApiClient.get('/tracks');
// response2 is from cache (instant return)

Disable Caching:

deduplicatedApiClient.get('/tracks', { _disableCache: true });

Integration Points

API Client Integration

Location: apps/web/src/services/api/client.ts:1155-1169

Behavior:

  • GET requests check cache first
  • Cache hit → Return immediately (no network request)
  • Cache miss → Proceed with request, cache response

Cache Check Flow:

  1. Check if _disableCache flag is set → Skip cache
  2. Generate cache key
  3. Check cache for key
  4. Validate cache entry (TTL, ETag, Last-Modified)
  5. Return cached response if valid, otherwise fetch

Response Caching

Location: apps/web/src/services/api/client.ts:482-483 (response interceptor)

Current Status: Responses ARE cached automatically

Implementation:

// In response interceptor (line 482-483)
if (method === 'GET' && !(response.config as any)?._disableCache) {
  responseCache.set(response.config, response);
}

Behavior: All GET requests are automatically cached unless _disableCache is set.

Verification

Correct Behavior

  1. GET-only: Only caches GET requests (safe)
  2. User-specific: Includes Authorization header in key (correct)
  3. Cache-Control: Respects server directives
  4. Size Limit: Maximum 100 entries with FIFO eviction
  5. Cleanup: Automatic cleanup every minute
  6. Invalidation: Manual invalidation via pattern matching

⚠️ Potential Issues

  1. Usage: Actually used in main apiClient response interceptor (verified)
  2. No Persistence: Cache cleared on page reload (expected but worth noting)
  3. ETag Not Used: ETag support exists but may not be fully utilized in practice
  4. Cache Invalidation: Automatic invalidation via stateInvalidation.ts after mutations (verified)

🔧 Recommendations

  1. Integration: Already integrated with main apiClient (verified)
  2. Invalidation: Automatic invalidation via stateInvalidation.ts (verified)
  3. ETag Usage: Verify ETag headers are being used for cache revalidation
  4. Metrics: Add metrics to track cache hit rate and effectiveness
  5. Documentation: Document cache behavior and when to use _disableCache flag

Current Usage

Files using responseCache directly:

  • apps/web/src/services/api/client.ts:482-483 - Automatic caching in response interceptor
  • apps/web/src/services/api/client.ts:1158 - Cache check in deduplicatedApiClient.get()
  • apps/web/src/utils/stateInvalidation.ts - Cache invalidation after mutations

Cache Invalidation:

  • stateInvalidation.ts clears/invalidates cache after mutations
  • Supports pattern-based invalidation (e.g., /tracks/*)

Status: Utility is actively used - Automatic caching for all GET requests

Testing Recommendations

  1. Unit Tests: Test cache key generation, validation, cleanup
  2. Integration Tests: Test with actual API calls, verify cache hits
  3. Edge Cases: Test cache expiration, size limits, invalidation patterns
  4. Performance: Measure cache hit rate and performance improvement

Documentation Status

Implementation documented
Usage patterns identified
Integration points verified
⚠️ Active usage needs verification
⚠️ Cache integration with main apiClient needs review
⏭️ Next: Action 2.5.1.7 - Test response cache works correctly

Validation

Utility implementation reviewed
Functionality verified
Integration points identified
Potential issues documented
Recommendations provided