cloud-game/web/js/workerManager.js
2023-04-26 20:08:20 +03:00

146 lines
4.6 KiB
JavaScript

/**
* Worker manager module.
* @version 1
*/
const workerManager = (() => {
const id = 'servers',
_class = 'server-list',
trigger = document.getElementById('w'),
panel = gui.panel(document.getElementById(id), 'WORKERS', 'server-list', null, [
{
caption: '⟳',
cl: ['bold'],
handler: utils.debounce(handleReload, 1000),
title: 'Reload server data',
}
],
// hack not transparent jpeg corners :_;
((br) => (state, el) => {
state ? el.parentElement.style.borderRadius = '0px' :
br ? el.parentElement.style.borderRadius = br :
br = window.getComputedStyle(el.parentElement).borderRadius
})()),
index = ((i = 1) => ({v: () => i++, r: () => i = 1}))(),
// caption -- the field caption
// renderer -- an arbitrary DOM output for the field
list = {
'n': {
renderer: renderIdEl
},
'id': {
caption: 'ID',
renderer: (data) => data?.in_group ? `${data.id} x ${data.replicas}` : data.id
},
'addr': {
caption: 'Address',
renderer: (data) => data?.port ? `${data.addr}:${data.port}` : data.addr
},
'is_busy': {
caption: 'State',
renderer: (data) => data?.is_busy === true ? 'R' : ''
},
'use': {
caption: 'Use',
renderer: renderServerChangeEl
}
},
fields = Object.keys(list);
let state = {
lastId: null,
workers: [],
}
const onNewData = (dat = {servers: []}) => {
panel.setLoad(false);
index.r();
state.workers = dat?.servers || [];
_render(state.workers);
}
function _render(servers = []) {
if (panel.isHidden()) return;
const content = gui.fragment();
if (servers.length === 0) {
content.append(gui.create('span', (el) => el.innerText = 'No data :('));
panel.setContent(content);
return;
}
const header = gui.create('div', (el) => {
el.classList.add(`${_class}__header`);
fields.forEach(field => el.append(gui.create('span', (f) => f.innerHTML = list[field]?.caption || '')))
});
content.append(header)
const renderRow = (server) => (row) => {
if (server?.id && state.lastId && state.lastId === server?.id) {
row.classList.add('active');
}
return fields.forEach(field => {
const val = server.hasOwnProperty(field) ? server[field] : '';
const renderer = list[field]?.renderer;
row.append(gui.create('span', (f) => f.append(renderer ? renderer(server) : val)));
})
}
servers.forEach(server => content.append(gui.create('div', renderRow(server))))
panel.setContent(content);
}
function handleReload() {
panel.setLoad(true);
api.server.getWorkerList();
}
function renderIdEl(server) {
const id = String(index.v()).padStart(2, '0');
const isActive = server?.id && state.lastId && state.lastId === server?.id
return `${(isActive ? '>' : '')}${id}`
}
function renderServerChangeEl(server) {
const handleServerChange = (e) => {
e.preventDefault();
window.location.search = `wid=${server.id}`
}
return gui.create('a', (el) => {
el.innerText = '>>';
el.href = "#";
el.addEventListener('click', handleServerChange);
})
}
panel.toggle(false);
trigger.addEventListener('click', () => {
handleReload();
panel.toggle(true);
})
const checkLatencies = (data) => {
const timeoutMs = 1111;
// deduplicate
const addresses = [...new Set(data.addresses || [])];
return Promise.all(addresses.map(address => {
const start = Date.now();
return ajax.fetch(`${address}?_=${start}`, {method: "GET", redirect: "follow"}, timeoutMs)
.then(() => ({[address]: Date.now() - start}))
.catch(() => ({[address]: 9999}));
}))
};
const whoami = (id) => {
state.lastId = id;
_render(state.workers);
}
event.sub(WORKER_LIST_FETCHED, onNewData);
return {
checkLatencies,
whoami,
}
})(ajax, api, document, event, gui, log, utils);