veza/apps/web/docs/OFFLINE_QUEUE_AUDIT.md
senke 8d251e0314 data-flow: audit offline queue utility
- Completed Action 2.5.1.3: Audited offlineQueue utility
- Created OFFLINE_QUEUE_AUDIT.md with complete analysis
- Verified core functionality: queue management, priority system, persistence, retry logic
- Verified integration: Error interceptor queues network errors (line 999-1007)
- Verified UI integration: OfflineIndicator displays queue size
- Documented queue configuration: 100 request limit, 3 retries, 24h expiry
- Identified potential issues: FormData serialization, token refresh on replay
- Provided recommendations for testing and improvements
2026-01-11 16:44:53 +01:00

6.8 KiB

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<void>

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

[
  {
    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:

// 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