Files
Projektarbeit-MYP/backend/static/js/performance-service-worker.min.js
Till Tomczak 956c24d8ca 🔧 Update: Enhanced error handling and logging across various modules
**Änderungen:**
-  app.py: Hinzugefügt, um CSRF-Fehler zu behandeln
-  models.py: Fehlerprotokollierung bei der Suche nach Gastanfragen per OTP
-  api.py: Fehlerprotokollierung beim Markieren von Benachrichtigungen als gelesen
-  calendar.py: Fallback-Daten zurückgeben, wenn keine Kalenderereignisse vorhanden sind
-  guest.py: Status-Check-Seite für Gäste aktualisiert
-  hardware_integration.py: Debugging-Informationen für erweiterte Geräteinformationen hinzugefügt
-  tapo_status_manager.py: Rückgabewert für Statusabfrage hinzugefügt

**Ergebnis:**
- Verbesserte Fehlerbehandlung und Protokollierung für eine robustere Anwendung
- Bessere Nachverfolgbarkeit von Fehlern und Systemverhalten

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-15 22:45:20 +02:00

1 line
9.7 KiB
JavaScript

const CACHE_VERSION='v2.0';const STATIC_CACHE=`myp-static-${CACHE_VERSION}`;const DYNAMIC_CACHE=`myp-dynamic-${CACHE_VERSION}`;const FONTS_CACHE=`myp-fonts-${CACHE_VERSION}`;const IMAGES_CACHE=`myp-images-${CACHE_VERSION}`;const CRITICAL_ASSETS=['/','/static/css/critical-inline.css','/static/css/app-bundle.min.css','/static/js/performance-service-worker.js','/static/js/app-bundle.min.js'];const CACHE_STRATEGIES={css:{cache:STATIC_CACHE,strategy:'cache-first',maxAge:86400000},js:{cache:STATIC_CACHE,strategy:'cache-first',maxAge:86400000},fonts:{cache:FONTS_CACHE,strategy:'cache-first',maxAge:2592000000},images:{cache:IMAGES_CACHE,strategy:'cache-first',maxAge:604800000},html:{cache:DYNAMIC_CACHE,strategy:'network-first',maxAge:3600000},api:{cache:DYNAMIC_CACHE,strategy:'network-first',maxAge:300000}};self.addEventListener('install',event=>{console.log('[SW] Installing Performance Service Worker...');event.waitUntil(Promise.all([caches.open(STATIC_CACHE).then(cache=>{console.log('[SW] Pre-caching critical assets...');return cache.addAll(CRITICAL_ASSETS).catch(err=>{console.warn('[SW] Failed to cache some assets:',err);});}),self.skipWaiting()]).catch(err=>{console.error('[SW] Installation failed:',err);}));});self.addEventListener('activate',event=>{console.log('[SW] Activating Performance Service Worker...');event.waitUntil(Promise.all([caches.keys().then(cacheNames=>{return Promise.all(cacheNames.map(cacheName=>{if(!cacheName.includes(CACHE_VERSION)){console.log('[SW] Deleting old cache:',cacheName);return caches.delete(cacheName);}}));}),self.clients.claim()]));});self.addEventListener('fetch',event=>{if(event.request.method!=='GET'||event.request.url.startsWith('chrome-extension:'))return;const url=new URL(event.request.url);const strategy=getResourceStrategy(url);event.respondWith(handleRequest(event.request,strategy));});function getResourceStrategy(url){const pathname=url.pathname;if(pathname.endsWith('.css'))return CACHE_STRATEGIES.css;if(pathname.endsWith('.js'))return CACHE_STRATEGIES.js;if(pathname.match(/\.(woff2?|ttf|eot)$/))return CACHE_STRATEGIES.fonts;if(pathname.match(/\.(jpg|jpeg|png|gif|webp|svg|ico)$/))return CACHE_STRATEGIES.images;if(pathname.startsWith('/api/'))return CACHE_STRATEGIES.api;return CACHE_STRATEGIES.html;}async function handleRequest(request,strategy){try{const cacheName=strategy.cache;switch(strategy.strategy){case'cache-first':return await cacheFirst(request,cacheName,strategy.maxAge);case'network-first':return await networkFirst(request,cacheName,strategy.maxAge);default:return await fetch(request);}}catch(error){console.error('[SW] Request handling failed:',error);return createFallbackResponse(request);}}async function cacheFirst(request,cacheName,maxAge){try{const cache=await caches.open(cacheName);const cachedResponse=await cache.match(request);if(cachedResponse&&!isExpired(cachedResponse,maxAge)){if(isCriticalResource(request.url)){updateInBackground(request,cache);}return cachedResponse;}const networkResponse=await fetchWithTimeout(request,5000);if(networkResponse&&networkResponse.ok){await cache.put(request,networkResponse.clone());return networkResponse;}return cachedResponse||createFallbackResponse(request);}catch(error){console.warn('[SW] Cache-first failed:',error);try{const cache=await caches.open(cacheName);const cachedResponse=await cache.match(request);return cachedResponse||createFallbackResponse(request);}catch(cacheError){console.error('[SW] Cache access failed:',cacheError);return createFallbackResponse(request);}}}async function networkFirst(request,cacheName,maxAge){try{const networkResponse=await fetchWithTimeout(request,3000);if(networkResponse&&networkResponse.ok){const cache=await caches.open(cacheName);await cache.put(request,networkResponse.clone()).catch(err=>{console.warn('[SW] Failed to cache response:',err);});return networkResponse;}throw new Error('Network response not ok');}catch(error){console.warn('[SW] Network-first fallback to cache:',error);try{const cache=await caches.open(cacheName);const cachedResponse=await cache.match(request);if(cachedResponse&&!isExpired(cachedResponse,maxAge)){return cachedResponse;}return createFallbackResponse(request);}catch(cacheError){console.error('[SW] Cache fallback failed:',cacheError);return createFallbackResponse(request);}}}function fetchWithTimeout(request,timeout){return new Promise((resolve,reject)=>{const timer=setTimeout(()=>reject(new Error('Timeout')),timeout);fetch(request).then(response=>{clearTimeout(timer);resolve(response);}).catch(error=>{clearTimeout(timer);reject(error);});});}function isExpired(response,maxAge){try{const date=response.headers.get('date');if(!date)return false;const responseTime=new Date(date).getTime();const now=Date.now();return(now-responseTime)>maxAge;}catch(error){console.warn('[SW] Error checking expiration:',error);return true;}}function isCriticalResource(url){return CRITICAL_ASSETS.some(asset=>url.includes(asset));}async function updateInBackground(request,cache){try{const response=await fetch(request);if(response&&response.ok){await cache.put(request,response);console.log('[SW] Background update completed for:',request.url);}}catch(error){console.warn('[SW] Background update failed:',error);}}function createFallbackResponse(request){try{const url=new URL(request.url);if(url.pathname.endsWith('.css')){return new Response(getFallbackCSS(),{status:200,statusText:'OK',headers:{'Content-Type':'text/css; charset=utf-8'}});}if(url.pathname.endsWith('.js')){return new Response('console.log("Fallback JS loaded");',{status:200,statusText:'OK',headers:{'Content-Type':'application/javascript; charset=utf-8'}});}if(url.pathname.match(/\.(jpg|jpeg|png|gif|webp)$/)){return new Response(getFallbackImage(),{status:200,statusText:'OK',headers:{'Content-Type':'image/svg+xml; charset=utf-8'}});}return new Response('Offline - Service nicht verfügbar',{status:503,statusText:'Service Unavailable',headers:{'Content-Type':'text/plain; charset=utf-8'}});}catch(error){console.error('[SW] Fallback response creation failed:',error);return new Response('Service Worker Error',{status:500,statusText:'Internal Server Error',headers:{'Content-Type':'text/plain; charset=utf-8'}});}}function getFallbackCSS(){return`body{font-family:system-ui,sans-serif;margin:0;padding:20px;background:#f8fafc;color:#1f2937}.offline{background:#fef3c7;border:1px solid#f59e0b;border-radius:8px;padding:16px;text-align:center;margin:20px 0}.btn{background:#0073ce;color:white;border:none;padding:8px 16px;border-radius:4px;cursor:pointer}.card{background:white;border:1px solid#e5e7eb;border-radius:8px;padding:16px;margin:16px 0}`;}function getFallbackImage(){return`<svg width="300"height="200"xmlns="http://www.w3.org/2000/svg"><rect width="100%"height="100%"fill="#f3f4f6"/><text x="50%"y="50%"text-anchor="middle"dy=".3em"fill="#6b7280">Bild offline</text></svg>`;}self.addEventListener('message',event=>{const{type,data}=event.data||{};switch(type){case'SKIP_WAITING':self.skipWaiting();break;case'CLEAR_ALL_CACHES':clearAllCaches().then(()=>{if(event.ports&&event.ports[0]){event.ports[0].postMessage({success:true});}}).catch(err=>{console.error('[SW] Clear caches failed:',err);if(event.ports&&event.ports[0]){event.ports[0].postMessage({success:false,error:err.message});}});break;case'PREFETCH_URLS':if(data&&data.urls){prefetchUrls(data.urls).then(()=>{if(event.ports&&event.ports[0]){event.ports[0].postMessage({success:true});}}).catch(err=>{console.error('[SW] Prefetch failed:',err);if(event.ports&&event.ports[0]){event.ports[0].postMessage({success:false,error:err.message});}});}break;case'GET_CACHE_INFO':getCacheInfo().then(info=>{if(event.ports&&event.ports[0]){event.ports[0].postMessage(info);}}).catch(err=>{console.error('[SW] Get cache info failed:',err);if(event.ports&&event.ports[0]){event.ports[0].postMessage({error:err.message});}});break;}});async function clearAllCaches(){try{const cacheNames=await caches.keys();await Promise.all(cacheNames.map(name=>caches.delete(name)));console.log('[SW] All caches cleared');}catch(error){console.error('[SW] Clear all caches failed:',error);throw error;}}async function prefetchUrls(urls){for(const url of urls){try{const response=await fetch(url);if(response&&response.ok){const strategy=getResourceStrategy(new URL(url));const cache=await caches.open(strategy.cache);await cache.put(url,response);console.log('[SW] Prefetched:',url);}}catch(error){console.warn('[SW] Prefetch failed for:',url,error);}}}async function getCacheInfo(){try{const cacheNames=await caches.keys();const info={};for(const name of cacheNames){try{const cache=await caches.open(name);const keys=await cache.keys();info[name]={entries:keys.length,urls:keys.map(req=>req.url)};}catch(error){console.warn('[SW] Failed to get info for cache:',name,error);info[name]={error:error.message};}}return info;}catch(error){console.error('[SW] Get cache info failed:',error);return{error:error.message};}}self.addEventListener('sync',event=>{if(event.tag==='background-sync'){console.log('[SW] Background sync triggered');event.waitUntil(doBackgroundSync());}});async function doBackgroundSync(){try{console.log('[SW] Background sync completed');}catch(error){console.error('[SW] Background sync failed:',error);}}console.log('[SW] Performance Service Worker loaded and ready');setTimeout(()=>{setInterval(async()=>{try{console.log('[SW] Starting automatic cache cleanup...');await cleanupOldCaches();}catch(error){console.error('[SW] Cache cleanup failed:',error);}},24*60*60*1000);},60000);async function cleanupOldCaches(){try{const cacheNames=await caches.keys();const oldCaches=cacheNames.filter(name=>!name.includes(CACHE_VERSION));await Promise.all(oldCaches.map(name=>{console.log('[SW] Cleaning up old cache:',name);return caches.delete(name);}));}catch(error){console.error('[SW] Cleanup old caches failed:',error);}}