Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m55s
260 lines
9.8 KiB
JavaScript
260 lines
9.8 KiB
JavaScript
/**
|
|
* Роуты планировщика карты сети: настройки, логи, ручной запуск, кеш.
|
|
*/
|
|
|
|
const { sendError, sendOk } = require('../middleware/errorHandler');
|
|
const { readS3TextObject, writeS3JsonObject } = require('../services/s3Service');
|
|
const networkMapScheduler = require('../services/networkMapScheduler');
|
|
const pingServicesScheduler = require('../services/pingServicesScheduler');
|
|
const uptimeMonitorScheduler = require('../services/uptimeMonitorScheduler');
|
|
|
|
const UI_SETTINGS_KEY = 'bgp_data/rt_ui_settings.json';
|
|
const NETWORK_MAP_CACHE_KEY = 'network-map-cache/latest.json';
|
|
|
|
const SCHEDULER_KEYS = [
|
|
'networkMapSchedulerEnabled',
|
|
'networkMapSchedulerIntervalMinutes',
|
|
'networkMapSchedulerRunPing',
|
|
'networkMapSchedulerRunSpeedTest',
|
|
'networkMapSchedulerLogMaxLines',
|
|
];
|
|
|
|
const PING_SERVICES_SCHEDULER_KEYS = [
|
|
'pingServicesSchedulerEnabled',
|
|
'pingServicesSchedulerIntervalMinutes',
|
|
];
|
|
|
|
const UPTIME_MONITOR_SCHEDULER_KEYS = [
|
|
'uptimeMonitorSchedulerEnabled',
|
|
'uptimeMonitorSchedulerIntervalMinutes',
|
|
];
|
|
|
|
async function readUiSettings() {
|
|
try {
|
|
const data = await readS3TextObject(UI_SETTINGS_KEY).catch(() => ({ body: '{}' }));
|
|
const parsed = JSON.parse(data?.body || '{}');
|
|
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
} catch (_) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/** GET /api/scheduler/network-map/settings */
|
|
async function getNetworkMapSchedulerSettings(req, res) {
|
|
try {
|
|
const ui = await readUiSettings();
|
|
const settings = networkMapScheduler.getSettingsFromUiSettings(ui);
|
|
const nextRunAt = networkMapScheduler.getNextRunAt(settings);
|
|
return res.json({ ...settings, nextRunAt: nextRunAt || undefined });
|
|
} catch (e) {
|
|
console.error('[scheduler] getSettings', e);
|
|
return sendError(res, 500, 'Не удалось прочитать настройки', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** PATCH /api/scheduler/network-map/settings - обновить только ключи планировщика в ui-settings */
|
|
async function patchNetworkMapSchedulerSettings(req, res) {
|
|
try {
|
|
const body = req.body || {};
|
|
const current = await readUiSettings();
|
|
for (const key of SCHEDULER_KEYS) {
|
|
if (Object.prototype.hasOwnProperty.call(body, key)) {
|
|
current[key] = body[key];
|
|
}
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(body, 'networkMapSchedulerLogMaxLines')) {
|
|
networkMapScheduler.setLogMaxLines(body.networkMapSchedulerLogMaxLines);
|
|
}
|
|
await writeS3JsonObject(UI_SETTINGS_KEY, current);
|
|
const settings = networkMapScheduler.getSettingsFromUiSettings(current);
|
|
return res.json(settings);
|
|
} catch (e) {
|
|
console.error('[scheduler] patchSettings', e);
|
|
return sendError(res, 500, 'Не удалось сохранить настройки', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** GET /api/scheduler/network-map/logs */
|
|
async function getNetworkMapSchedulerLogs(req, res) {
|
|
try {
|
|
const lines = networkMapScheduler.getLogs();
|
|
return res.json({ lines });
|
|
} catch (e) {
|
|
console.error('[scheduler] getLogs', e);
|
|
return sendError(res, 500, 'Не удалось прочитать логи', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** POST /api/scheduler/network-map/run-now - один запуск по текущим настройкам */
|
|
async function runNetworkMapSchedulerNow(req, res) {
|
|
try {
|
|
const port = Number(process.env.PORT) || 3001;
|
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
const ui = await readUiSettings();
|
|
const settings = networkMapScheduler.getSettingsFromUiSettings(ui);
|
|
|
|
networkMapScheduler.runJob({
|
|
baseUrl,
|
|
runPing: settings.runPing,
|
|
runSpeedTest: settings.runSpeedTest,
|
|
trigger: 'manual',
|
|
}).catch((err) => {
|
|
console.error('[scheduler] run-now failed', err);
|
|
const msg = err?.message || String(err);
|
|
try {
|
|
networkMapScheduler.pushLog(`Ошибка выполнения: ${msg}`);
|
|
} catch (_) {}
|
|
});
|
|
|
|
return res.json({ ok: true, message: 'Запуск выполняется в фоне' });
|
|
} catch (e) {
|
|
console.error('[scheduler] run-now', e);
|
|
const msg = e?.message || String(e);
|
|
try {
|
|
networkMapScheduler.pushLog(`Ошибка запуска: ${msg}`);
|
|
} catch (_) {}
|
|
return sendError(res, 500, 'Не удалось запустить', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** GET /api/network-map-cache - кеш пингов и скоростей для карты сети */
|
|
async function getNetworkMapCache(req, res) {
|
|
try {
|
|
const data = await readS3TextObject(NETWORK_MAP_CACHE_KEY).catch(() => null);
|
|
if (!data?.body) {
|
|
return res.json({ pingMap: {}, speedMap: {}, updatedAt: null });
|
|
}
|
|
const parsed = JSON.parse(data.body);
|
|
return res.json({
|
|
pingMap: parsed.pingMap && typeof parsed.pingMap === 'object' ? parsed.pingMap : {},
|
|
speedMap: parsed.speedMap && typeof parsed.speedMap === 'object' ? parsed.speedMap : {},
|
|
updatedAt: typeof parsed.updatedAt === 'number' ? parsed.updatedAt : null,
|
|
});
|
|
} catch (e) {
|
|
console.error('[network-map-cache] get', e);
|
|
return res.json({ pingMap: {}, speedMap: {}, updatedAt: null });
|
|
}
|
|
}
|
|
|
|
// === Ping services scheduler ===
|
|
|
|
/** GET /api/scheduler/ping-services/settings */
|
|
async function getPingServicesSchedulerSettings(req, res) {
|
|
try {
|
|
const ui = await readUiSettings();
|
|
const settings = pingServicesScheduler.getSettingsFromUiSettings(ui);
|
|
const nextRunAt = pingServicesScheduler.getNextRunAt(settings);
|
|
return res.json({ ...settings, nextRunAt: nextRunAt || undefined });
|
|
} catch (e) {
|
|
console.error('[scheduler] getPingServicesSettings', e);
|
|
return sendError(res, 500, 'Не удалось прочитать настройки', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** PATCH /api/scheduler/ping-services/settings */
|
|
async function patchPingServicesSchedulerSettings(req, res) {
|
|
try {
|
|
const body = req.body || {};
|
|
const current = await readUiSettings();
|
|
for (const key of PING_SERVICES_SCHEDULER_KEYS) {
|
|
if (Object.prototype.hasOwnProperty.call(body, key)) {
|
|
current[key] = body[key];
|
|
}
|
|
}
|
|
await writeS3JsonObject(UI_SETTINGS_KEY, current);
|
|
const settings = pingServicesScheduler.getSettingsFromUiSettings(current);
|
|
return res.json(settings);
|
|
} catch (e) {
|
|
console.error('[scheduler] patchPingServicesSettings', e);
|
|
return sendError(res, 500, 'Не удалось сохранить настройки', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** POST /api/scheduler/ping-services/run-now */
|
|
async function runPingServicesSchedulerNow(req, res) {
|
|
try {
|
|
const { refreshPingServicesCache } = require('./miscRoutes');
|
|
refreshPingServicesCache().catch((err) => {
|
|
console.error('[scheduler] ping-services run-now failed', err);
|
|
});
|
|
return res.json({ ok: true, message: 'Обновление кеша пинг-сервисов запущено в фоне' });
|
|
} catch (e) {
|
|
console.error('[scheduler] ping-services run-now', e);
|
|
return sendError(res, 500, 'Не удалось запустить', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
// === Uptime monitor scheduler ===
|
|
|
|
/** GET /api/scheduler/uptime-monitor/settings */
|
|
async function getUptimeMonitorSchedulerSettings(req, res) {
|
|
try {
|
|
const ui = await readUiSettings();
|
|
const settings = uptimeMonitorScheduler.getSettingsFromUiSettings(ui);
|
|
const nextRunAt = uptimeMonitorScheduler.getNextRunAt(settings);
|
|
return res.json({ ...settings, nextRunAt: nextRunAt || undefined });
|
|
} catch (e) {
|
|
console.error('[scheduler] getUptimeMonitorSettings', e);
|
|
return sendError(res, 500, 'Не удалось прочитать настройки', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** PATCH /api/scheduler/uptime-monitor/settings */
|
|
async function patchUptimeMonitorSchedulerSettings(req, res) {
|
|
try {
|
|
const body = req.body || {};
|
|
const current = await readUiSettings();
|
|
for (const key of UPTIME_MONITOR_SCHEDULER_KEYS) {
|
|
if (Object.prototype.hasOwnProperty.call(body, key)) {
|
|
current[key] = body[key];
|
|
}
|
|
}
|
|
await writeS3JsonObject(UI_SETTINGS_KEY, current);
|
|
const settings = uptimeMonitorScheduler.getSettingsFromUiSettings(current);
|
|
return res.json(settings);
|
|
} catch (e) {
|
|
console.error('[scheduler] patchUptimeMonitorSettings', e);
|
|
return sendError(res, 500, 'Не удалось сохранить настройки', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
/** POST /api/scheduler/uptime-monitor/run-now */
|
|
async function runUptimeMonitorSchedulerNow(req, res) {
|
|
try {
|
|
const port = Number(process.env.PORT) || 3001;
|
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
const resServers = await fetch(`${baseUrl}/api/servers`).catch(() => null);
|
|
const data = resServers?.ok ? await resServers.json() : [];
|
|
const servers = Array.isArray(data) ? data : [];
|
|
const jumphosts = servers.filter(
|
|
(s) => s && ['jumphost', 'home'].includes(String(s.type || '').toLowerCase())
|
|
);
|
|
const serverIds = jumphosts.map((s) => s.id || s.dns || s.ip).filter(Boolean);
|
|
for (const serverId of serverIds) {
|
|
fetch(`${baseUrl}/api/uptime/check`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ serverId }),
|
|
}).catch((err) => console.warn('[scheduler] uptime check', serverId, err?.message));
|
|
}
|
|
return res.json({ ok: true, message: 'Проверки Uptime Monitor запущены в фоне' });
|
|
} catch (e) {
|
|
console.error('[scheduler] uptime-monitor run-now', e);
|
|
return sendError(res, 500, 'Не удалось запустить', 'E_SCHEDULER');
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getNetworkMapSchedulerSettings,
|
|
patchNetworkMapSchedulerSettings,
|
|
getNetworkMapSchedulerLogs,
|
|
runNetworkMapSchedulerNow,
|
|
getNetworkMapCache,
|
|
getPingServicesSchedulerSettings,
|
|
patchPingServicesSchedulerSettings,
|
|
runPingServicesSchedulerNow,
|
|
getUptimeMonitorSchedulerSettings,
|
|
patchUptimeMonitorSchedulerSettings,
|
|
runUptimeMonitorSchedulerNow,
|
|
};
|