veza/apps/web/docs/OFFLINE_QUEUE_AUDIT.md

197 lines
6.8 KiB
Markdown
Raw Normal View History

# 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
```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