soundwave/DEBUG_OFFLINE.md
Iulian 9bdce32219 Fix CORS configuration for PWA offline caching
- Add CORS_ALLOWED_ORIGINS environment variable support in Django settings
- Use environment variable in docker-compose.yml (no hardcoded domains)
- Update .env.example with CORS configuration documentation
- Add comprehensive PWA offline debugging guide

SECURITY: Private domains should be set in local .env file, not in repo
2025-12-24 01:26:00 +00:00

4.7 KiB

🐛 Debugging Offline Playlist Caching

Issue

User clicks "Make Available Offline" but playlists aren't being cached for offline playback.

Investigation Steps

1. Check Service Worker Registration

Open browser DevTools → Console and run:

navigator.serviceWorker.getRegistration().then(reg => console.log('SW Registered:', reg))

Expected: ServiceWorkerRegistration object If null: Service worker isn't registered

2. Check if Service Worker is Active

navigator.serviceWorker.ready.then(reg => console.log('SW Active:', reg.active))

Expected: ServiceWorker object with state 'activated'

3. Test Message Passing

Open a playlist page and run in console:

const testCache = async () => {
  const reg = await navigator.serviceWorker.ready;
  const messageChannel = new MessageChannel();
  
  messageChannel.port1.onmessage = (event) => {
    console.log('Response from SW:', event.data);
  };
  
  reg.active.postMessage(
    { 
      type: 'CACHE_PLAYLIST', 
      playlistId: 'test123',
      audioUrls: ['/api/audio/test/download/']
    },
    [messageChannel.port2]
  );
};

testCache();

Expected: Console log showing response from service worker

4. Check Network Requests

When clicking "Make Available Offline":

  1. Open DevTools → Network tab
  2. Filter by "audio"
  3. Click the button
  4. Check if audio download requests are made

Expected: Multiple requests to /api/audio/{id}/download/

5. Check Service Worker Console

  1. Open DevTools → Application tab
  2. Click "Service Workers"
  3. Click "inspect" next to the active service worker
  4. New DevTools window opens showing SW console
  5. Try caching again and watch for logs

Expected logs:

  • [Service Worker] Message received: {type: 'CACHE_PLAYLIST', ...}
  • [Service Worker] Caching playlist: ...
  • [Service Worker] Cached audio: ...

6. Check Cache Storage

After attempting to cache:

  1. DevTools → Application → Cache Storage
  2. Look for soundwave-audio-v1 cache
  3. Expand it to see cached files

Expected: Audio files should be listed

7. Check IndexedDB

  1. DevTools → Application → IndexedDB
  2. Look for SoundwaveOfflineDB
  3. Check playlists object store

Expected: Playlist with offline: true

Common Issues

Issue 1: Service Worker Not Registered

Symptom: navigator.serviceWorker.getRegistration() returns null

Fix: Check if running on HTTPS or localhost. Service workers require secure context.

Issue 2: CORS / Authentication Issues

Symptom: Network requests fail with 401/403

Fix: Ensure audio download endpoints properly handle authentication. Check service worker creates authenticated requests:

const authRequest = new Request(url, {
  credentials: 'include',
  headers: { 'Accept': 'audio/*' }
});

Issue 3: Message Channel Not Working

Symptom: No response from service worker

Fix: Ensure service worker message handler properly uses event.ports[0].postMessage()

Issue 4: Service Worker Scope Issues

Symptom: Fetch events not intercepting

Fix: Check service worker registered with scope: '/'

Quick Test Script

Run this in browser console on a playlist page:

const debugOfflineCache = async () => {
  console.log('=== Offline Cache Debug ===');
  
  // 1. Check SW
  const reg = await navigator.serviceWorker.getRegistration();
  console.log('1. SW Registered:', !!reg);
  console.log('   SW Active:', reg?.active?.state);
  
  // 2. Check if online
  console.log('2. Online:', navigator.onLine);
  
  // 3. Check IndexedDB
  const db = await new Promise((resolve, reject) => {
    const request = indexedDB.open('SoundwaveOfflineDB');
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
  console.log('3. IndexedDB:', db.name, 'version:', db.version);
  
  // 4. Check cache storage
  const cacheNames = await caches.keys();
  console.log('4. Caches:', cacheNames);
  
  for (const name of cacheNames) {
    const cache = await caches.open(name);
    const keys = await cache.keys();
    console.log(`   ${name}:`, keys.length, 'entries');
  }
  
  // 5. Test cache size
  if ('storage' in navigator && 'estimate' in navigator.storage) {
    const estimate = await navigator.storage.estimate();
    const usage = (estimate.usage / 1024 / 1024).toFixed(2);
    const quota = (estimate.quota / 1024 / 1024).toFixed(2);
    console.log('5. Storage: ', usage, 'MB /', quota, 'MB');
  }
  
  console.log('=== Debug Complete ===');
};

debugOfflineCache();

Next Steps

Based on debug output, identify which component is failing:

  • Service Worker registration
  • Message passing
  • Network requests
  • Cache storage
  • IndexedDB storage