Efficient websocket tiles

This commit is contained in:
Romein van Buren 2023-02-25 14:38:57 +01:00
parent 6f9e34ee6d
commit 5967941008
Signed by: romein
GPG Key ID: 0EFF8478ADDF6C49

149
index.js
View File

@ -326,90 +326,101 @@ module.exports = {
order: 100, order: 100,
purpose: 'Start the websocket for the dashboard after boot', purpose: 'Start the websocket for the dashboard after boot',
handler: () => { handler: () => {
const timers = {};
let tiles = [];
let downIdsBefore = []; let downIdsBefore = [];
let downIdsAfter = []; let downIdsAfter = [];
let newOutage = false; let newOutage = false;
const mapService = (s, beat) => ({ function mapService(s, beat) {
id: s.id, return {
name: s.name, id: s.id,
cluster: s.cluster, name: s.name,
lastBeat: beat, cluster: s.cluster,
checked: s.lastChecked, lastBeat: beat,
}); checked: s.lastChecked,
};
}
async function getTiles() {
const services = await server.storage
.store('smartyellow/webservice')
.find({ public: true })
.toArray();
const heartbeats = await server.storage
.store('smartyellow/webserviceheartbeat')
.find({ webservice: { $in: services.map(s => s.id) } })
.sort({ date: -1 })
.toArray();
tiles = [];
for (let service of services) {
const beat = heartbeats.find(b => b.webservice === service.id);
service = mapService(service, beat);
const tile = {
service: service,
serviceId: service.id,
badges: [],
prio: -1,
};
if (!beat) {
tile.prio = -1; // no data (grey)
tile.statusText = 'no data';
}
else if (beat.down) {
tile.prio = 2; // down (red)
tile.statusText = 'down';
downIdsAfter.push(tile.serviceId);
}
else {
tile.prio = 0; // ok (green)
tile.statusText = 'ok';
}
tiles.push(tile);
}
// Let other plugins enrich dashboard tiles with custom badges and priorities.
await server.executePreHooks('populateDashboardTiles', { tiles });
await server.executePostHooks('populateDashboardTiles', { tiles });
await server.executePostHooks('pupulateDashboardTiles', { tiles }); // backwards compatibility
// Check if there are new outages and report them by ringing a bell on the dashboard.
newOutage = false;
for (const id of downIdsAfter) {
if (!downIdsBefore.includes(id)) {
newOutage = true;
}
}
downIdsBefore = [ ...downIdsAfter ];
downIdsAfter = [];
}
// Load tiles every 10 seconds.
setInterval(getTiles, 10000);
server.ws({ server.ws({
route: '/status/dashboard/socket', route: '/status/dashboard/socket',
onOpen: async ws => { onOpen: async ws => {
async function sendStatuses() { function sendTiles() {
const services = await server.storage
.store('smartyellow/webservice')
.find({ public: true })
.toArray();
const heartbeats = await server.storage
.store('smartyellow/webserviceheartbeat')
.find({ webservice: { $in: services.map(s => s.id) } })
.sort({ date: -1 })
.toArray();
const tiles = [];
for (let service of services) {
const beat = heartbeats.find(b => b.webservice === service.id);
service = mapService(service, beat);
const tile = {
service: service,
serviceId: service.id,
badges: [],
prio: -1,
};
if (!beat) {
tile.prio = -1; // no data (grey)
tile.statusText = 'no data';
}
else if (beat.down) {
tile.prio = 2; // down (red)
tile.statusText = 'down';
downIdsAfter.push(tile.serviceId);
}
else {
tile.prio = 0; // ok (green)
tile.statusText = 'ok';
}
tiles.push(tile);
}
// Let other plugins enrich dashboard tiles with custom badges and priorities.
await server.executePreHooks('populateDashboardTiles', { tiles });
await server.executePostHooks('populateDashboardTiles', { tiles });
await server.executePostHooks('pupulateDashboardTiles', { tiles }); // backwards compatibility
// Check if there are new outages and report them by ringing a bell on the dashboard.
newOutage = false;
for (const id of downIdsAfter) {
if (!downIdsBefore.includes(id)) {
newOutage = true;
}
}
downIdsBefore = [ ...downIdsAfter ];
downIdsAfter = [];
try { try {
const json = JSON.stringify({ newOutage, tiles }); const json = JSON.stringify({ newOutage, tiles });
ws.send(json); ws.send(json);
} }
catch { catch { /* noop */ }
return;
}
} }
// Send statuses on open and every 5 seconds. // Send tiles on open and every 5 seconds.
sendStatuses(); sendTiles();
setInterval(sendStatuses, 5000); timers[ws.id] = setInterval(sendTiles, 5000);
},
onUpgrade: () => ({ id: makeId(10) }),
onMessage: () => { /* nevermind */ },
onClose: ws => {
clearInterval(timers[ws.id]);
delete timers[ws.id];
}, },
onUpgrade: async () => ({ id: makeId(10) }),
onMessage: async () => { /* do nothing */ },
}); });
}, },
}, },