Files
awesome-app/public/worker.js
valknarness b63592f153 a new start
2025-10-25 16:09:02 +02:00

171 lines
4.1 KiB
JavaScript

/**
* Awesome Web Worker
* Intelligently polls for database updates and manages cache invalidation
*/
const POLL_INTERVAL = 5 * 60 * 1000; // 5 minutes
const DB_VERSION_ENDPOINT = '/api/db-version';
let currentDbVersion = null;
let pollTimer = null;
// Smart polling with exponential backoff
class SmartPoller {
constructor(interval) {
this.baseInterval = interval;
this.currentInterval = interval;
this.maxInterval = interval * 4;
this.minInterval = interval / 2;
this.consecutiveErrors = 0;
}
increaseInterval() {
this.currentInterval = Math.min(this.currentInterval * 1.5, this.maxInterval);
console.log('[Worker] Increased poll interval to', this.currentInterval / 1000, 'seconds');
}
decreaseInterval() {
this.currentInterval = Math.max(this.currentInterval * 0.75, this.minInterval);
console.log('[Worker] Decreased poll interval to', this.currentInterval / 1000, 'seconds');
}
resetInterval() {
this.currentInterval = this.baseInterval;
}
getInterval() {
return this.currentInterval;
}
}
const poller = new SmartPoller(POLL_INTERVAL);
// Check for database updates
async function checkForUpdates() {
try {
const response = await fetch(DB_VERSION_ENDPOINT, {
method: 'GET',
headers: {
'Cache-Control': 'no-cache',
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
// First time or version changed
if (currentDbVersion === null) {
currentDbVersion = data.version;
console.log('[Worker] Initial DB version:', currentDbVersion);
} else if (data.version !== currentDbVersion) {
console.log('[Worker] New DB version detected!', data.version);
// Notify all clients
const clients = await self.clients.matchAll();
clients.forEach(client => {
client.postMessage({
type: 'DB_UPDATE',
version: data.version,
metadata: data,
});
});
currentDbVersion = data.version;
// Invalidate cache
await invalidateCache();
}
// Reset error counter and adjust interval
poller.consecutiveErrors = 0;
poller.resetInterval();
} catch (error) {
console.error('[Worker] Poll failed:', error);
poller.consecutiveErrors++;
if (poller.consecutiveErrors > 3) {
poller.increaseInterval();
}
}
}
// Invalidate cache
async function invalidateCache() {
try {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames.map(cacheName => {
if (cacheName.includes('awesome')) {
console.log('[Worker] Clearing cache:', cacheName);
return caches.delete(cacheName);
}
})
);
console.log('[Worker] Cache invalidated');
} catch (error) {
console.error('[Worker] Cache invalidation failed:', error);
}
}
// Start polling
function startPolling() {
if (pollTimer) {
clearInterval(pollTimer);
}
// Initial check
checkForUpdates();
// Schedule periodic checks
pollTimer = setInterval(() => {
checkForUpdates();
}, poller.getInterval());
console.log('[Worker] Polling started');
}
// Stop polling
function stopPolling() {
if (pollTimer) {
clearInterval(pollTimer);
pollTimer = null;
console.log('[Worker] Polling stopped');
}
}
// Service Worker event listeners
self.addEventListener('install', (event) => {
console.log('[Worker] Installing...');
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
console.log('[Worker] Activated');
event.waitUntil(self.clients.claim());
startPolling();
});
self.addEventListener('message', (event) => {
console.log('[Worker] Message received:', event.data);
if (event.data.type === 'CHECK_UPDATE') {
checkForUpdates();
} else if (event.data.type === 'START_POLLING') {
startPolling();
} else if (event.data.type === 'STOP_POLLING') {
stopPolling();
}
});
// Fetch event - cache strategy
self.addEventListener('fetch', (event) => {
// Add caching strategy here if needed
event.respondWith(fetch(event.request));
});