fix: Résolution des blocages après l'enregistrement du Service Worker
- 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
This commit is contained in:
parent
17517f861a
commit
937b071100
@ -120,7 +120,7 @@ export class Database {
|
|||||||
// No existing workers: register a new one.
|
// No existing workers: register a new one.
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' });
|
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' });
|
||||||
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
|
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
|
||||||
|
|
||||||
// Show spinner during service worker initialization
|
// Show spinner during service worker initialization
|
||||||
this.showServiceWorkerSpinner('Initializing database service...');
|
this.showServiceWorkerSpinner('Initializing database service...');
|
||||||
} else if (registrations.length === 1) {
|
} else if (registrations.length === 1) {
|
||||||
@ -135,12 +135,21 @@ export class Database {
|
|||||||
console.log('All previous Service Workers unregistered.');
|
console.log('All previous Service Workers unregistered.');
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' });
|
this.serviceWorkerRegistration = await navigator.serviceWorker.register(path, { type: 'module' });
|
||||||
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
|
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
|
||||||
|
|
||||||
// Show spinner during service worker initialization
|
// Show spinner during service worker initialization
|
||||||
this.showServiceWorkerSpinner('Initializing database service...');
|
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
|
// Hide spinner once service worker is ready
|
||||||
this.hideServiceWorkerSpinner();
|
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.
|
// Set up a periodic check to ensure the service worker is active and to send a SCAN message.
|
||||||
this.serviceWorkerCheckIntervalId = window.setInterval(async () => {
|
this.serviceWorkerCheckIntervalId = window.setInterval(async () => {
|
||||||
const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!));
|
try {
|
||||||
const service = await Services.getInstance();
|
const activeWorker = this.serviceWorkerRegistration?.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration!));
|
||||||
const payload = await service.getMyProcesses();
|
if (activeWorker) {
|
||||||
if (payload && payload.length != 0) {
|
const service = await Services.getInstance();
|
||||||
activeWorker?.postMessage({ type: 'SCAN', payload });
|
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) {
|
} catch (error) {
|
||||||
console.error('Service Worker registration failed:', error);
|
console.error('Service Worker registration failed:', error);
|
||||||
}
|
}
|
||||||
@ -167,18 +183,28 @@ export class Database {
|
|||||||
|
|
||||||
// Helper function to wait for service worker activation
|
// Helper function to wait for service worker activation
|
||||||
private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise<ServiceWorker | null> {
|
private async waitForServiceWorkerActivation(registration: ServiceWorkerRegistration): Promise<ServiceWorker | null> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (registration.active) {
|
if (registration.active) {
|
||||||
resolve(registration.active);
|
resolve(registration.active);
|
||||||
} else {
|
return;
|
||||||
const listener = () => {
|
|
||||||
if (registration.active) {
|
|
||||||
navigator.serviceWorker.removeEventListener('controllerchange', listener);
|
|
||||||
resolve(registration.active);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
navigator.serviceWorker.addEventListener('controllerchange', listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) {
|
if (this.serviceWorkerRegistration) {
|
||||||
// Check for updates to the service worker
|
// Check for updates to the service worker
|
||||||
try {
|
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 there's a new worker waiting, activate it immediately
|
||||||
if (this.serviceWorkerRegistration.waiting) {
|
if (this.serviceWorkerRegistration.waiting) {
|
||||||
@ -194,6 +223,7 @@ export class Database {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error checking for service worker updates:', 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
|
// Save data to db
|
||||||
const blob = new Blob([valueBytes], {type: "application/octet-stream"});
|
const blob = new Blob([valueBytes], {type: "application/octet-stream"});
|
||||||
await service.saveBlobToDb(hash, blob);
|
await service.saveBlobToDb(hash, blob);
|
||||||
document.dispatchEvent(new CustomEvent('newDataReceived', {
|
document.dispatchEvent(new CustomEvent('newDataReceived', {
|
||||||
detail: {
|
detail: {
|
||||||
processId,
|
processId,
|
||||||
stateId,
|
stateId,
|
||||||
hash,
|
hash,
|
||||||
@ -330,7 +360,7 @@ export class Database {
|
|||||||
reject(new Error(`Failed to send message to service worker: ${error}`));
|
reject(new Error(`Failed to send message to service worker: ${error}`));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise<void> {
|
public batchWriting(payload: { storeName: string; objects: { key: any; object: any }[] }): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
@ -462,7 +492,7 @@ export class Database {
|
|||||||
private showServiceWorkerSpinner(message: string = 'Initializing...') {
|
private showServiceWorkerSpinner(message: string = 'Initializing...') {
|
||||||
// Remove existing spinner if any
|
// Remove existing spinner if any
|
||||||
this.hideServiceWorkerSpinner();
|
this.hideServiceWorkerSpinner();
|
||||||
|
|
||||||
// Create spinner overlay
|
// Create spinner overlay
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
overlay.id = 'service-worker-spinner-overlay';
|
overlay.id = 'service-worker-spinner-overlay';
|
||||||
@ -480,7 +510,7 @@ export class Database {
|
|||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Create spinner content
|
// Create spinner content
|
||||||
const spinnerContent = document.createElement('div');
|
const spinnerContent = document.createElement('div');
|
||||||
spinnerContent.style.cssText = `
|
spinnerContent.style.cssText = `
|
||||||
@ -493,7 +523,7 @@ export class Database {
|
|||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Create spinner
|
// Create spinner
|
||||||
const spinner = document.createElement('div');
|
const spinner = document.createElement('div');
|
||||||
spinner.style.cssText = `
|
spinner.style.cssText = `
|
||||||
@ -505,7 +535,7 @@ export class Database {
|
|||||||
animation: spin 1s linear infinite;
|
animation: spin 1s linear infinite;
|
||||||
margin: 0 auto 15px auto;
|
margin: 0 auto 15px auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Create message
|
// Create message
|
||||||
const messageEl = document.createElement('div');
|
const messageEl = document.createElement('div');
|
||||||
messageEl.textContent = message;
|
messageEl.textContent = message;
|
||||||
@ -515,7 +545,7 @@ export class Database {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Create progress indicator
|
// Create progress indicator
|
||||||
const progressEl = document.createElement('div');
|
const progressEl = document.createElement('div');
|
||||||
progressEl.textContent = 'Please wait...';
|
progressEl.textContent = 'Please wait...';
|
||||||
@ -523,7 +553,7 @@ export class Database {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #666;
|
color: #666;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Add CSS animation if not already present
|
// Add CSS animation if not already present
|
||||||
if (!document.getElementById('service-worker-spinner-styles')) {
|
if (!document.getElementById('service-worker-spinner-styles')) {
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
@ -536,13 +566,13 @@ export class Database {
|
|||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assemble spinner
|
// Assemble spinner
|
||||||
spinnerContent.appendChild(spinner);
|
spinnerContent.appendChild(spinner);
|
||||||
spinnerContent.appendChild(messageEl);
|
spinnerContent.appendChild(messageEl);
|
||||||
spinnerContent.appendChild(progressEl);
|
spinnerContent.appendChild(progressEl);
|
||||||
overlay.appendChild(spinnerContent);
|
overlay.appendChild(spinnerContent);
|
||||||
|
|
||||||
// Add to document
|
// Add to document
|
||||||
document.body.appendChild(overlay);
|
document.body.appendChild(overlay);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user