Refactor database.service
This commit is contained in:
parent
aa22b78121
commit
b7a2f3a058
@ -8,6 +8,7 @@ export class Database {
|
|||||||
private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;
|
private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;
|
||||||
private messageChannel: MessageChannel | null = null;
|
private messageChannel: MessageChannel | null = null;
|
||||||
private messageChannelForGet: MessageChannel | null = null;
|
private messageChannelForGet: MessageChannel | null = null;
|
||||||
|
private serviceWorkerCheckIntervalId: number | null = null;
|
||||||
private storeDefinitions = {
|
private storeDefinitions = {
|
||||||
AnkLabels: {
|
AnkLabels: {
|
||||||
name: 'labels',
|
name: 'labels',
|
||||||
@ -81,12 +82,10 @@ export class Database {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
request.onsuccess = () => {
|
request.onsuccess = async () => {
|
||||||
setTimeout(() => {
|
this.db = request.result;
|
||||||
this.db = request.result;
|
await this.initServiceWorker();
|
||||||
this.initServiceWorker();
|
resolve();
|
||||||
resolve();
|
|
||||||
}, 500);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
request.onerror = () => {
|
request.onerror = () => {
|
||||||
@ -115,43 +114,43 @@ export class Database {
|
|||||||
if (!('serviceWorker' in navigator)) return; // Ensure service workers are supported
|
if (!('serviceWorker' in navigator)) return; // Ensure service workers are supported
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get existing service worker registrations
|
// Get existing service worker registrations
|
||||||
const registrations = await navigator.serviceWorker.getRegistrations();
|
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||||
if (registrations.length === 0) {
|
if (registrations.length === 0) {
|
||||||
// No existing workers: register a new one.
|
// No existing workers: register a new one.
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.register('/src/service-workers/database.worker.js', { type: 'module' });
|
this.serviceWorkerRegistration = await navigator.serviceWorker.register('/src/service-workers/database.worker.js', { type: 'module' });
|
||||||
console.log('Service Worker registered with scope:', registration.scope);
|
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
|
||||||
} else if (registrations.length === 1) {
|
} else if (registrations.length === 1) {
|
||||||
// One existing worker: update it (restart it) without unregistering.
|
// One existing worker: update it (restart it) without unregistering.
|
||||||
this.serviceWorkerRegistration = registrations[0];
|
this.serviceWorkerRegistration = registrations[0];
|
||||||
await this.serviceWorkerRegistration.update();
|
await this.serviceWorkerRegistration.update();
|
||||||
console.log('Service worker updated');
|
console.log('Service Worker updated');
|
||||||
} else {
|
} else {
|
||||||
// More than one existing worker: unregister them all and register a new one.
|
// More than one existing worker: unregister them all and register a new one.
|
||||||
console.log('Multiple Service Worker(s) detected. Unregistering all...');
|
console.log('Multiple Service Worker(s) detected. Unregistering all...');
|
||||||
await Promise.all(registrations.map(reg => reg.unregister()));
|
await Promise.all(registrations.map(reg => reg.unregister()));
|
||||||
console.log('All previous Service Workers unregistered.');
|
console.log('All previous Service Workers unregistered.');
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.register('/src/service-workers/database.worker.js', { type: 'module' });
|
this.serviceWorkerRegistration = await navigator.serviceWorker.register('/src/service-workers/database.worker.js', { type: 'module' });
|
||||||
console.log('Service Worker registered with scope:', registration.scope);
|
console.log('Service Worker registered with scope:', this.serviceWorkerRegistration.scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.checkForUpdates();
|
await this.checkForUpdates();
|
||||||
|
|
||||||
// Set up the message channels
|
// Set up a global message listener for responses from the service worker.
|
||||||
this.messageChannel = new MessageChannel();
|
navigator.serviceWorker.addEventListener('message', async (event) => {
|
||||||
this.messageChannelForGet = new MessageChannel();
|
console.log('Received message from service worker:', event.data);
|
||||||
this.messageChannel.port1.onmessage = this.handleAddObjectResponse;
|
await this.handleServiceWorkerMessage(event.data);
|
||||||
this.messageChannelForGet.port1.onmessage = this.handleGetObjectResponse;
|
});
|
||||||
|
|
||||||
// Ensure the new service worker is activated before sending messages
|
// Set up a periodic check to ensure the service worker is active and to send a SYNC message.
|
||||||
|
this.serviceWorkerCheckIntervalId = window.setInterval(async () => {
|
||||||
const activeWorker = this.serviceWorkerRegistration.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration));
|
const activeWorker = this.serviceWorkerRegistration.active || (await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration));
|
||||||
|
const service = await Services.getInstance();
|
||||||
activeWorker?.postMessage(
|
const payload = await service.getMyProcesses();
|
||||||
{ type: 'START' },
|
activeWorker?.postMessage({ type: 'SCAN', payload });
|
||||||
[this.messageChannel.port2],
|
}, 5000);
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Service Worker registration failed:', error);
|
console.error('Service Worker registration failed:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +187,46 @@ export class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async handleServiceWorkerMessage(message: any) {
|
||||||
|
switch (message.type) {
|
||||||
|
case 'TO_DOWNLOAD':
|
||||||
|
console.log('Received data to download:', message.data);
|
||||||
|
await this.handleDownloadList(message.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn('Unknown message type received from service worker:', message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleDownloadList(downloadList: string[]): void {
|
||||||
|
// Download the missing data
|
||||||
|
let requestedStateId = [];
|
||||||
|
const service = await Services.getInstance();
|
||||||
|
for (const hash of downloadList) {
|
||||||
|
try {
|
||||||
|
const valueBytes = await service.fetchValueFromStorage(hash);
|
||||||
|
if (valueBytes) {
|
||||||
|
// Save data to db
|
||||||
|
const blob = new Blob([valueBytes], {type: "application/octet-stream"});
|
||||||
|
await service.saveBlobToDb(hash, blob);
|
||||||
|
} else {
|
||||||
|
// We first request the data from managers
|
||||||
|
console.log('Request data from managers of the process');
|
||||||
|
// get the diff from db
|
||||||
|
const diff = await service.getDiffByValue(hash);
|
||||||
|
const processId = diff.process_id;
|
||||||
|
const stateId = diff.state_id;
|
||||||
|
if (!requestedStateId.includes(stateId)) {
|
||||||
|
await service.requestDataFromPeers(processId, stateId);
|
||||||
|
requestedStateId.push(stateId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private handleAddObjectResponse = async (event: MessageEvent) => {
|
private handleAddObjectResponse = async (event: MessageEvent) => {
|
||||||
const data = event.data;
|
const data = event.data;
|
||||||
console.log('Received response from service worker (ADD_OBJECT):', data);
|
console.log('Received response from service worker (ADD_OBJECT):', data);
|
||||||
@ -195,6 +234,7 @@ export class Database {
|
|||||||
if (data.type === 'NOTIFICATIONS') {
|
if (data.type === 'NOTIFICATIONS') {
|
||||||
service.setNotifications(data.data);
|
service.setNotifications(data.data);
|
||||||
} else if (data.type === 'TO_DOWNLOAD') {
|
} else if (data.type === 'TO_DOWNLOAD') {
|
||||||
|
console.log(`Received missing data ${data}`);
|
||||||
// Download the missing data
|
// Download the missing data
|
||||||
let requestedStateId = [];
|
let requestedStateId = [];
|
||||||
for (const hash of data.data) {
|
for (const hash of data.data) {
|
||||||
@ -220,8 +260,6 @@ export class Database {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try to update list of my processes
|
|
||||||
await service.getMyProcesses();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -267,49 +305,6 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateMyProcesses(myProcessesId: string[]): Promise<void> {
|
|
||||||
if (myProcessesId.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
if (!this.serviceWorkerRegistration) {
|
|
||||||
// console.warn('Service worker registration is not ready. Waiting...');
|
|
||||||
this.serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeWorker = await this.waitForServiceWorkerActivation(this.serviceWorkerRegistration);
|
|
||||||
// Create a message channel for communication
|
|
||||||
const messageChannel = new MessageChannel();
|
|
||||||
|
|
||||||
// Handle the response from the service worker
|
|
||||||
messageChannel.port1.onmessage = (event) => {
|
|
||||||
if (event.data.status === 'success') {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
const error = event.data.message;
|
|
||||||
reject(new Error(error || 'Unknown error occurred while scanning our processes'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const payload = { myProcessesId };
|
|
||||||
console.log('Sending UPDATE_PROCESSES msg with payload', payload);
|
|
||||||
activeWorker?.postMessage(
|
|
||||||
{
|
|
||||||
type: 'UPDATE_PROCESSES',
|
|
||||||
|
|
||||||
payload,
|
|
||||||
},
|
|
||||||
[messageChannel.port2],
|
|
||||||
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
reject(new Error(`Failed to send message to service worker: ${error}`));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getObject(storeName: string, key: string): Promise<any | null> {
|
public async getObject(storeName: string, key: string): Promise<any | null> {
|
||||||
const db = await this.getDb();
|
const db = await this.getDb();
|
||||||
const tx = db.transaction(storeName, 'readonly');
|
const tx = db.transaction(storeName, 'readonly');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user