# Offline Queue Utility Audit **Date**: 2025-01-27 **Action**: 2.5.1.3 - Audit offlineQueue utility **Status**: ✅ Complete ## Overview This document audits the `offlineQueue` utility to verify it works correctly and documents its usage. ## File Location - **Source**: `apps/web/src/services/offlineQueue.ts` - **Exports**: `offlineQueue` (singleton instance), `QueuedRequest`, `QueueOptions` - **Purpose**: Queue failed requests when offline and replay when connection is restored ## Implementation Analysis ### Core Functionality The utility stores failed requests due to network issues and replays them when connection is restored. **Key Features**: 1. **Offline Detection**: Uses `navigator.onLine` API 2. **Request Queuing**: Stores failed mutation requests (POST, PUT, DELETE, PATCH) 3. **Priority Support**: High, normal, low priority levels 4. **Persistent Storage**: Saves queue to localStorage 5. **Automatic Replay**: Processes queue when connection restored 6. **Retry Logic**: Maximum 3 retries with exponential backoff ### Queue Configuration **Default Settings**: - **Max Queue Size**: 100 requests - **Default Max Retries**: 3 attempts - **Default Retry Delay**: 1 second (increases with retry count) - **Request Expiry**: 24 hours (old requests filtered on load) ### Request Filtering **Method**: `shouldQueueRequest(config: AxiosRequestConfig): boolean` **Rules**: - ❌ **GET requests**: Not queued (can be retried fresh when online) - ✅ **Mutations**: POST, PUT, DELETE, PATCH are queued - **Rationale**: GET requests are idempotent and can be retried, mutations need to be preserved ### Queue Management **Priority System**: - **High priority**: Processed first - **Normal priority**: Processed after high - **Low priority**: Processed last, first to be evicted if queue is full **Queue Eviction**: - If queue is full (100 requests): 1. Try to remove oldest low-priority request 2. If no low-priority, remove oldest request (FIFO) **Queue Persistence**: - Saved to `localStorage` key: `veza_offline_queue` - Loaded on service initialization - Old requests (>24 hours) filtered out on load ### Queue Processing **Method**: `processQueue(): Promise` **Processing Flow**: 1. Check if already processing or offline → Skip 2. Process requests in priority order (high → normal → low) 3. Retry each request via `apiClient.request()` 4. On success → Remove from queue 5. On failure → Increment retry count 6. Max retries reached → Remove from queue (failed) 7. Otherwise → Move to end of queue for retry 8. Delay between requests (100ms) to avoid overwhelming server 9. Exponential backoff on retries **Online Event Listener**: - Listens for `window.addEventListener('online')` - Automatically processes queue when connection restored ### Storage Format **localStorage Key**: `veza_offline_queue` **Storage Format**: JSON array of `QueuedRequest` objects ```typescript [ { id: "req_1234567890_abc123", config: { method: "POST", url: "/tracks", data: {...} }, timestamp: 1234567890000, retryCount: 0, priority: "normal" } ] ``` **Limitations**: - AxiosRequestConfig may contain non-serializable data (functions, File objects) - File uploads may not serialize correctly to JSON ## Integration Points ### API Client Integration **Location**: `apps/web/src/services/api/client.ts:999-1007` (error interceptor) **Actual Implementation**: ```typescript // FE-API-015: Queue request for offline replay if it's a network error if (!error.response && originalRequest && offlineQueue.shouldQueueRequest(originalRequest)) { const priority = originalRequest.method === 'POST' ? 'high' : 'normal'; try { await offlineQueue.queueRequest(originalRequest, { priority }); } catch (queueError) { logger.error('[API] Failed to queue request for offline replay', { error: queueError }); } } ``` **Behavior**: - ✅ Queues network errors (no response received) - ✅ Only queues mutations (POST, PUT, DELETE, PATCH) - ✅ Priority: POST = high, others = normal - ✅ Error handling: Catches queue errors gracefully **Status**: ✅ **Verified - Fully integrated** ### Current Usage **Files using `offlineQueue`**: - ✅ `apps/web/src/services/api/client.ts:999-1007` - **Error interceptor queues network errors** - ✅ `apps/web/src/components/OfflineIndicator.tsx` - Shows queue size in UI - ✅ `apps/web/src/services/api/client.ts:204` - `processQueue()` function (may be related) **UI Integration**: - `OfflineIndicator.tsx` displays queue size - Updates when queue size changes **Status**: ✅ **Utility is actively used and integrated** ## Verification ### ✅ Correct Behavior 1. **Offline Detection**: Uses `navigator.onLine` API 2. **Request Filtering**: Only queues mutations (correct) 3. **Priority System**: High/normal/low priority support 4. **Persistence**: Saves to localStorage, survives page reloads 5. **Automatic Replay**: Processes queue on online event 6. **Retry Logic**: Exponential backoff, max 3 retries 7. **Queue Limits**: Maximum 100 requests, FIFO eviction 8. **Old Request Cleanup**: Filters requests older than 24 hours ### ⚠️ Potential Issues 1. **Serialization**: AxiosRequestConfig may contain non-serializable data (File objects, functions) 2. **File Uploads**: FormData/file uploads may not serialize correctly to JSON 3. ✅ **Integration**: Verified - Error interceptor queues network errors (line 999-1007) 4. ✅ **Error Filtering**: Only queues network errors (`!error.response`) - Correct behavior 5. **Token Refresh**: Queued requests may have expired tokens when replayed (needs verification) ### 🔧 Recommendations 1. ✅ **Integration**: Verified - Error interceptor queues requests correctly 2. **File Upload Handling**: Special handling for FormData/file uploads (may need to skip queueing or handle differently) 3. **Token Refresh**: Verify tokens are refreshed before replaying queued requests 4. ✅ **Error Filtering**: Already correct - Only queues network errors 5. ✅ **UI Feedback**: Already implemented - OfflineIndicator shows queue size 6. **Testing**: Test with actual offline scenarios, file uploads, token expiration ## Testing Recommendations 1. **Unit Tests**: Test queueing, priority, persistence, retry logic 2. **Integration Tests**: Test with actual API calls, offline simulation 3. **Edge Cases**: Test queue full, old requests, file uploads, token expiration 4. **Browser Testing**: Test `navigator.onLine` behavior across browsers ## Documentation Status ✅ Implementation documented ✅ Usage patterns identified ✅ Integration verified (error interceptor) ✅ UI integration verified (OfflineIndicator) ⏭️ Next: Action 2.5.1.4 - Add UI for offline queue management (may already be partially implemented) ## Validation ✅ Utility implementation reviewed ✅ Functionality verified ✅ Integration points identified ✅ Potential issues documented ✅ Recommendations provided