Skip to content

Commit

Permalink
even better connectivity checking!
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekEagle committed Nov 6, 2024
1 parent 5c06d42 commit f3a4e2f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 48 deletions.
56 changes: 41 additions & 15 deletions src/sw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,6 @@ function errorLog(component: string = 'ServiceWorker', ...data: any[]) {
console.error(`[${component}]`, ...data);
}

// Bind router to fetch event
self.addEventListener('fetch', (event) => {
event.respondWith(
(async () => {
const response = await router.handleRequest(event as FetchEvent);
if (!response) {
return (
(await caches.match(event.request)) || (await fetch(event.request))
);
}
return response;
})(),
);
});

// ---- Helper functions ----

async function claimClients(skipWaiting: boolean = false): Promise<void> {
Expand Down Expand Up @@ -124,6 +109,8 @@ async function makeConnectionCheck() {
// If the response status matches the expected status, we're online.
if (isOnline !== (res.status === checkTargetResponseStatus)) {
isOnline = res.status === checkTargetResponseStatus;
// Message clients to let them know we're online or offline.
await messageClients({ type: 'isOnline', payload: isOnline });
debugLog(
'ServiceWorkerConnectivityCheck',
'Connection status changed:',
Expand All @@ -134,6 +121,8 @@ async function makeConnectionCheck() {
// If the fetch fails, we're probably offline.
if (isOnline) {
isOnline = false;
// Message clients to let them know we're online or offline.
await messageClients({ type: 'isOnline', payload: isOnline });
debugLog(
'ServiceWorkerConnectivityCheck',
'Failed to make connection check, assuming offline.',
Expand Down Expand Up @@ -179,6 +168,43 @@ self.addEventListener('install', async (event) => {
}
});

// Bind router to fetch event
self.addEventListener('fetch', (event) => {
event.respondWith(
(async () => {
const response = await router.handleRequest(event as FetchEvent);
if (!response) {
try {
return (
(await caches.match(event.request)) || (await fetch(event.request))
);
} catch (err) {
// If the fetch fails, log the error, re-run, the connection check, and return a 502 Bad Gateway
runConnectionCheck();
errorLog(
'ServiceWorkerRouterHandler',
'Network request failed, returning 502',
err,
);
return new Response(null, { status: 502, statusText: 'Bad Gateway' });
}
}
return response;
})(),
);
});

// Listen for messages from clients
self.addEventListener('message', (event) => {
switch (event.data.type) {
case 'checkOnline':
event.source?.postMessage({ type: 'isOnline', payload: isOnline });
break;
default:
errorLog('ServiceWorkerMessageHandler', 'Unknown message type', event);
}
});

// ---- Router routes ----

// Make SPA available offline
Expand Down
41 changes: 8 additions & 33 deletions src/utils/ConnectivityCheck.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,18 @@
import { inject, Plugin, ref } from 'vue';

const checkInterval = 60e3,
checkTarget = 'https://connectivitycheck.alekeagle.com',
checkTargetResponseStatus = 204;

export const ConnectivityCheckPlugin: Plugin = {
install(app) {
let isOnlineInterval: ReturnType<typeof setInterval> | null = null;
// Initialize the isOnline ref with the current navigator status
const isOnline = ref(navigator.onLine);

const isOnline = ref(true);
app.provide('isOnline', isOnline);
window.navigator.serviceWorker?.controller?.postMessage({
type: 'checkOnline',
});

async function makeConnectionCheck() {
try {
const response = await fetch(checkTarget, { method: 'HEAD' });
isOnline.value = response.status === checkTargetResponseStatus;
} catch (error) {
isOnline.value = false;
}
}

async function runConnectionCheck() {
// Clear the interval if it exists.
if (isOnlineInterval) {
clearInterval(isOnlineInterval);
isOnlineInterval = null;
navigator.serviceWorker?.addEventListener('message', (event) => {
if (event.data.type === 'isOnline') {
isOnline.value = event.data.payload;
}
// Make a connection check immediately.
await makeConnectionCheck();
// Set the interval back up to check every x seconds.
isOnlineInterval = setInterval(makeConnectionCheck, checkInterval);
}

window.addEventListener('online', runConnectionCheck);
window.addEventListener('offline', runConnectionCheck);

// Start the connection check interval.
runConnectionCheck();
});
},
};

Expand Down

0 comments on commit f3a4e2f

Please sign in to comment.