186 lines
6.5 KiB
TypeScript
186 lines
6.5 KiB
TypeScript
/**
|
|
* Service Worker sync handler - executes sync operations in main thread
|
|
* Listens to requests from Service Worker and executes them
|
|
*/
|
|
|
|
import { platformSyncService } from './platformSync'
|
|
import { syncUserContentToCache } from './userContentSync'
|
|
import { publishWorker } from './publishWorker'
|
|
import { nostrService } from './nostr'
|
|
import { swClient } from './swClient'
|
|
import type { Event } from 'nostr-tools'
|
|
|
|
class ServiceWorkerSyncHandler {
|
|
private initialized = false
|
|
|
|
/**
|
|
* Initialize the sync handler
|
|
* Sets up message listeners from Service Worker
|
|
*/
|
|
async initialize(): Promise<void> {
|
|
if (this.initialized) {
|
|
return
|
|
}
|
|
|
|
if (typeof window === 'undefined') {
|
|
return
|
|
}
|
|
|
|
try {
|
|
await swClient.register()
|
|
this.registerMessageHandlers()
|
|
|
|
this.initialized = true
|
|
console.warn('[SWSyncHandler] Initialized')
|
|
} catch (error) {
|
|
console.error('[SWSyncHandler] Initialization failed:', error)
|
|
}
|
|
}
|
|
|
|
private registerMessageHandlers(): void {
|
|
swClient.onMessage('SYNC_REQUEST', (data: unknown) => {
|
|
void this.handleSyncRequestMessage(data)
|
|
})
|
|
swClient.onMessage('PUBLISH_WORKER_REQUEST', () => {
|
|
void this.handlePublishWorkerRequest()
|
|
})
|
|
swClient.onMessage('PUBLISH_REQUEST', (data: unknown) => {
|
|
void this.handlePublishRequestMessage(data)
|
|
})
|
|
swClient.onMessage('NOTIFICATION_DETECT_REQUEST', (data: unknown) => {
|
|
void this.handleNotificationDetectRequestMessage(data)
|
|
})
|
|
}
|
|
|
|
private async handleSyncRequestMessage(data: unknown): Promise<void> {
|
|
const syncData = data as { syncType: string; userPubkey?: string }
|
|
if (syncData.syncType === 'platform') {
|
|
await this.handlePlatformSyncRequest()
|
|
return
|
|
}
|
|
if (syncData.syncType === 'user' && syncData.userPubkey) {
|
|
await this.handleUserSyncRequest(syncData.userPubkey)
|
|
}
|
|
}
|
|
|
|
private async handlePublishRequestMessage(data: unknown): Promise<void> {
|
|
const publishData = data as { event: Event; relays: string[] }
|
|
await this.handlePublishRequest(publishData.event, publishData.relays)
|
|
}
|
|
|
|
private async handleNotificationDetectRequestMessage(data: unknown): Promise<void> {
|
|
const detectData = data as { userPubkey: string }
|
|
await this.handleNotificationDetectRequest(detectData.userPubkey)
|
|
}
|
|
|
|
/**
|
|
* Handle platform sync request from Service Worker
|
|
*/
|
|
private async handlePlatformSyncRequest(): Promise<void> {
|
|
try {
|
|
console.warn('[SWSyncHandler] Executing platform sync request')
|
|
await platformSyncService.startSync()
|
|
} catch (error) {
|
|
console.error('[SWSyncHandler] Error in platform sync:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle user sync request from Service Worker
|
|
*/
|
|
private async handleUserSyncRequest(userPubkey: string): Promise<void> {
|
|
try {
|
|
console.warn('[SWSyncHandler] Executing user sync request for:', userPubkey)
|
|
await syncUserContentToCache(userPubkey)
|
|
} catch (error) {
|
|
console.error('[SWSyncHandler] Error in user sync:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle publish worker request from Service Worker
|
|
*/
|
|
private async handlePublishWorkerRequest(): Promise<void> {
|
|
try {
|
|
console.warn('[SWSyncHandler] Executing publish worker request')
|
|
// Trigger publish worker processing
|
|
// The publishWorker will process unpublished objects
|
|
await publishWorker['processUnpublished']()
|
|
} catch (error) {
|
|
console.error('[SWSyncHandler] Error in publish worker:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle notification detection request from Service Worker
|
|
* Le Service Worker détecte les changements indépendamment
|
|
* Ce handler exécute la détection dans le thread principal et crée les notifications via writeService
|
|
*/
|
|
private async handleNotificationDetectRequest(userPubkey: string): Promise<void> {
|
|
try {
|
|
console.warn('[SWSyncHandler] Executing notification detection request for:', userPubkey)
|
|
const { notificationDetector } = await import('./notificationDetector')
|
|
|
|
// Scanner IndexedDB pour détecter les nouveaux événements
|
|
await notificationDetector.scan()
|
|
|
|
// Les notifications sont créées via notificationDetector qui utilise notificationService
|
|
// qui utilise maintenant writeService pour écrire via Web Worker
|
|
} catch (error) {
|
|
console.error('[SWSyncHandler] Error in notification detection:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle publish request from Service Worker
|
|
* Uses websocketService to route events to Service Worker
|
|
*/
|
|
private async handlePublishRequest(event: Event, relays: string[]): Promise<void> {
|
|
try {
|
|
console.warn('[SWSyncHandler] Executing publish request for event:', event.id)
|
|
const { websocketService } = await import('./websocketService')
|
|
const { publishLog } = await import('./publishLog')
|
|
|
|
// Publish to specified relays via websocketService (routes to Service Worker)
|
|
const statuses = await websocketService.publishEvent(event, relays)
|
|
const successfulRelays = logPublishStatuses({ publishLog, eventId: event.id, relays, statuses })
|
|
|
|
// Update published status in IndexedDB
|
|
await updatePublishedStatusUnsafe(event.id, successfulRelays.length > 0 ? successfulRelays : false)
|
|
} catch (error) {
|
|
console.error('[SWSyncHandler] Error in publish request:', error)
|
|
}
|
|
}
|
|
}
|
|
|
|
export const swSyncHandler = new ServiceWorkerSyncHandler()
|
|
|
|
function logPublishStatuses(params: {
|
|
publishLog: { logPublication: (params: { eventId: string; relayUrl: string; success: boolean; error?: string }) => Promise<void> }
|
|
eventId: string
|
|
relays: string[]
|
|
statuses: Array<{ success: boolean; error?: string }>
|
|
}): string[] {
|
|
const successfulRelays: string[] = []
|
|
params.statuses.forEach((status, index) => {
|
|
const relayUrl = params.relays[index]
|
|
if (!relayUrl) {
|
|
return
|
|
}
|
|
if (status.success) {
|
|
successfulRelays.push(relayUrl)
|
|
void params.publishLog.logPublication({ eventId: params.eventId, relayUrl, success: true })
|
|
return
|
|
}
|
|
const errorMessage = status.error ?? 'Unknown error'
|
|
console.error(`[SWSyncHandler] Relay ${relayUrl} failed:`, errorMessage)
|
|
void params.publishLog.logPublication({ eventId: params.eventId, relayUrl, success: false, error: errorMessage })
|
|
})
|
|
return successfulRelays
|
|
}
|
|
|
|
async function updatePublishedStatusUnsafe(eventId: string, published: false | string[]): Promise<void> {
|
|
const service = nostrService as unknown as { updatePublishedStatus: (eventId: string, published: false | string[]) => Promise<void> }
|
|
await service.updatePublishedStatus(eventId, published)
|
|
}
|