From 937b071100ba06ba2cc0afd8983e1a3571c9fa64 Mon Sep 17 00:00:00 2001 From: NicolasCantu Date: Wed, 22 Oct 2025 16:07:24 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20R=C3=A9solution=20des=20blocages=20apr?= =?UTF-8?q?=C3=A8s=20l'enregistrement=20du=20Service=20Worker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout de timeouts sur checkForUpdates() (10s) et waitForServiceWorkerActivation() (15s) - Gestion d'erreur améliorée pour éviter les blocages infinis - checkForUpdates() avec timeout de 5s pour éviter les blocages - waitForServiceWorkerActivation() retourne null au lieu de bloquer - Gestion d'erreur dans l'intervalle de scan du service worker - Continuation de l'initialisation même en cas d'échec partiel - Logs d'avertissement pour diagnostiquer les problèmes --- src/services/database.service.ts | 90 +++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/src/services/database.service.ts b/src/services/database.service.ts index abb5fe2..665ca0c 100755 --- a/src/services/database.service.ts +++ b/src/services/database.service.ts @@ -120,7 +120,7 @@ export class Database { // No existing workers: register a new one. this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' }); console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope); - + // Show spinner during service worker initialization this.showServiceWorkerSpinner('Initializing database service...'); } else if (registrations.length === 1) { @@ -135,12 +135,21 @@ export class Database { console.log('All previous Service Workers unregistered.'); this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' }); console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope); - + // Show spinner during service worker initialization this.showServiceWorkerSpinner('Initializing database service...'); } - await this.checkForUpdates(); + // Check for updates with timeout + try { + await Promise.race([ + this.checkForUpdates(), + new Promise((_, reject) => setTimeout(() => reject(new Error('Update timeout')), 10000)) + ]); + } catch (error) { + console.warn('Service worker update failed or timed out:', error); + // Continue anyway - don't block the initialization + } // Hide spinner once service worker is ready this.hideServiceWorkerSpinner(); @@ -153,13 +162,20 @@ export class Database { // Set up a periodic check to ensure the service worker is active and to send a SCAN message. this.serviceWorkerCheckIntervalId = window.setInterval(async () => { - const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!)); - const service = await Services.getInstance(); - const payload = await service.getMyProcesses(); - if (payload && payload.length != 0) { - activeWorker?.postMessage({ type: 'SCAN', payload }); + try { + const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!)); + if (activeWorker) { + const service = await Services.getInstance(); + const payload = await service.getMyProcesses(); + if (payload && payload.length != 0) { + activeWorker.postMessage({ type: 'SCAN', payload }); + } + } + } catch (error) { + console.warn('Service worker scan failed:', error); + // Continue the interval even if one scan fails } - }, 5000); + }, 5000); } catch (error) { console.error('Service Worker registration failed:', error); } @@ -167,18 +183,28 @@ export class Database { // Helper function to wait for service worker activation private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise { - return new Promise((resolve) => { + return new Promise((resolve, reject) => { if (registration.active) { resolve(registration.active); - } else { - const listener = () => { - if (registration.active) { - navigator.serviceWorker.removeEventListener('controllerchange', listener); - resolve(registration.active); - } - }; - navigator.serviceWorker.addEventListener('controllerchange', listener); + return; } + + // Set a timeout to prevent infinite waiting + const timeout = setTimeout(() => { + navigator.serviceWorker.removeEventListener('controllerchange', listener); + console.warn('Service worker activation timeout'); + resolve(null); // Return null instead of rejecting to allow continuation + }, 15000); // 15 second timeout + + const listener = () => { + if (registration.active) { + clearTimeout(timeout); + navigator.serviceWorker.removeEventListener('controllerchange', listener); + resolve(registration.active); + } + }; + + navigator.serviceWorker.addEventListener('controllerchange', listener); }); } @@ -186,7 +212,10 @@ export class Database { if (this.serviceWorkerRegistration) { // Check for updates to the service worker try { - await this.serviceWorkerRegistration.update(); + await Promise.race([ + this.serviceWorkerRegistration.update(), + new Promise((_, reject) => setTimeout(() => reject(new Error('Update timeout')), 5000)) + ]); // If there's a new worker waiting, activate it immediately if (this.serviceWorkerRegistration.waiting) { @@ -194,6 +223,7 @@ export class Database { } } catch (error) { console.error('Error checking for service worker updates:', error); + throw error; // Re-throw to be caught by the calling function } } } @@ -228,8 +258,8 @@ export class Database { // Save data to db const blob = new Blob([valueBytes], {type: "application/octet-stream"}); await service.saveBlobToDb(hash, blob); - document.dispatchEvent(new CustomEvent('newDataReceived', { - detail: { + document.dispatchEvent(new CustomEvent('newDataReceived', { + detail: { processId, stateId, hash, @@ -330,7 +360,7 @@ export class Database { reject(new Error(`Failed to send message to service worker: ${error}`)); } }); - } + } public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise { return new Promise(async (resolve, reject) => { @@ -462,7 +492,7 @@ export class Database { private showServiceWorkerSpinner(message: string = 'Initializing...') { // Remove existing spinner if any this.hideServiceWorkerSpinner(); - + // Create spinner overlay const overlay = document.createElement('div'); overlay.id = 'service-worker-spinner-overlay'; @@ -480,7 +510,7 @@ export class Database { z-index: 10000; backdrop-filter: blur(5px); `; - + // Create spinner content const spinnerContent = document.createElement('div'); spinnerContent.style.cssText = ` @@ -493,7 +523,7 @@ export class Database { max-width: 400px; width: 90%; `; - + // Create spinner const spinner = document.createElement('div'); spinner.style.cssText = ` @@ -505,7 +535,7 @@ export class Database { animation: spin 1s linear infinite; margin: 0 auto 15px auto; `; - + // Create message const messageEl = document.createElement('div'); messageEl.textContent = message; @@ -515,7 +545,7 @@ export class Database { font-weight: 500; margin-bottom: 10px; `; - + // Create progress indicator const progressEl = document.createElement('div'); progressEl.textContent = 'Please wait...'; @@ -523,7 +553,7 @@ export class Database { font-size: 12px; color: #666; `; - + // Add CSS animation if not already present if (!document.getElementById('service-worker-spinner-styles')) { const style = document.createElement('style'); @@ -536,13 +566,13 @@ export class Database { `; document.head.appendChild(style); } - + // Assemble spinner spinnerContent.appendChild(spinner); spinnerContent.appendChild(messageEl); spinnerContent.appendChild(progressEl); overlay.appendChild(spinnerContent); - + // Add to document document.body.appendChild(overlay); }