Files
go-service/cmd/server/web/js/app.js
2026-05-09 12:21:38 +03:00

152 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app.js (оркестратор)
import { fetchHealth, fetchHistory } from "./data.js";
import { state, smooth, addSignal } from "./state.js";
import {
initDOM,
setStatus,
setMeta,
setBars,
setSignal,
DOM
} from "./ui.js";
import { initAccordion } from "./accordion.js";
import { drawChart } from "./chart.js";
let lastChart = 0;
let connectionLost = false;
let consecutiveErrors = 0; // счётчик ошибок подряд
const MAX_ERRORS = 3; // после скольки ошибок замедляем опрос
let pollTimer = null; // храним ID таймера для возможности сброса
// ================= INIT =================
window.addEventListener("DOMContentLoaded", () => {
initDOM();
initAccordion();
});
// ================= UPDATE =================
async function update() {
try {
const [h, hist] = await Promise.all([
fetchHealth(),
fetchHistory()
]);
consecutiveErrors = 0;
if (connectionLost) {
console.log("[app] Соединение восстановлено");
}
// ===== STATUS =====
const isOnline = h.pipe_alive && h.has_data;
if (isOnline) {
setStatus("На связи");
connectionLost = false;
} else {
setStatus("Нет связи", true);
connectionLost = true;
}
const arr = Array.isArray(hist.bytes) ? hist.bytes : [];
const raw = arr[arr.length - 1] ?? 0;
// ===== DECODE =====
const value = raw & 0x3F;
const level = (raw >> 6) & 0x3;
const percent = (value / 63) * 100;
// ===== STATE =====
addSignal(value);
// ===== UI =====
if (isOnline) {
setBars(smooth(percent));
setSignal(level);
} else {
setBars(0, true);
setSignal(0, true);
}
if (DOM.lastByte) {
DOM.lastByte.textContent = isOnline ? value : "--";
}
// ===== META =====
const uptime = Math.round(h.uptime_sec || 0);
const filled = h.stats?.filled ?? 0;
const bps = Math.round(h.stats?.bits_per_sec ?? 0);
const Bps = Math.round(h.stats?.bytes_per_sec ?? 0);
const idle = Math.round((h.last_data_ms || 0) / 1000);
setMeta(
`работа: ${uptime}s | буфер: ${filled} | ${bps} bit/s (${Bps} B/s) | idle: ${idle}s`
);
// ===== HISTORY =====
if (DOM.history) {
DOM.history.innerHTML = arr
.map((b, i) =>
`[${i}] ${(b & 0xFF).toString(2).padStart(8, "0")} = ${b & 0xFF}`
)
.join("<br>");
}
// ===== CHART =====
const now = performance.now();
if (now - lastChart > 100 && DOM.canvas) {
drawChart(DOM.canvas, state.signalHistory);
lastChart = now;
}
} catch (e) {
consecutiveErrors++;
if (consecutiveErrors === 1) {
console.warn("[app] Сервер недоступен, ждём...");
}
setStatus("СЕРВЕР НЕДОСТУПЕН", true);
setBars(0, true);
setSignal(0, true);
if (DOM.lastByte) {
DOM.lastByte.textContent = "--";
}
if (consecutiveErrors >= MAX_ERRORS) {
clearInterval(pollTimer);
pollTimer = setInterval(update, 2000);
console.log("[app] Замедлили опрос до 2с");
}
}
}
// ================= RECONNECT LOGIC =================
function startPolling() {
if (pollTimer) clearInterval(pollTimer);
// Если были ошибки — сразу пробуем переподключиться
if (consecutiveErrors > 0) {
console.log("[app] Попытка переподключения...");
update();
}
pollTimer = setInterval(update, 500);
}
// Сброс при фокусе окна (пользователь вернулся — пробуем быстро)
window.addEventListener("focus", () => {
if (consecutiveErrors >= MAX_ERRORS) {
console.log("[app] Окно в фокусе, ускоряем опрос");
consecutiveErrors = 0;
startPolling();
}
});
// ================= START =================
startPolling();
update();