feat(NetworkMapScheduler): enhance job execution logging and add force refresh option for ping and speed tests
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m44s

This commit is contained in:
2026-02-18 13:23:03 +07:00
parent b1834e988b
commit 89d71ff060
3 changed files with 33 additions and 8 deletions
+3 -1
View File
@@ -514,6 +514,7 @@ async function pingViaInterface(req, res) {
interfaceName, interfaceName,
target, target,
count = 5, count = 5,
forceRefresh = false,
} = req.body || {}; } = req.body || {};
if (!serverId) { if (!serverId) {
@@ -528,7 +529,8 @@ async function pingViaInterface(req, res) {
} }
const pingCacheMinutes = Math.max(0, parseInt(uiSettings.pingCacheMinutes, 10) || 0); const pingCacheMinutes = Math.max(0, parseInt(uiSettings.pingCacheMinutes, 10) || 0);
const cacheKey = pingCacheMinutes > 0 ? pingCacheKey(serverId, gatewayIp, target) : null; const cacheKey = pingCacheMinutes > 0 ? pingCacheKey(serverId, gatewayIp, target) : null;
if (cacheKey) { const skipCacheRead = forceRefresh === true;
if (!skipCacheRead && cacheKey) {
try { try {
const data = await readS3TextObject(cacheKey).catch(() => null); const data = await readS3TextObject(cacheKey).catch(() => null);
if (data?.body) { if (data?.body) {
+9
View File
@@ -84,13 +84,22 @@ async function runNetworkMapSchedulerNow(req, res) {
baseUrl, baseUrl,
runPing: settings.runPing, runPing: settings.runPing,
runSpeedTest: settings.runSpeedTest, runSpeedTest: settings.runSpeedTest,
trigger: 'manual',
}).catch((err) => { }).catch((err) => {
console.error('[scheduler] run-now failed', err); console.error('[scheduler] run-now failed', err);
const msg = err?.message || String(err);
try {
networkMapScheduler.pushLog(`Ошибка выполнения: ${msg}`);
} catch (_) {}
}); });
return sendOk(res, { message: 'Запуск выполняется в фоне' }); return sendOk(res, { message: 'Запуск выполняется в фоне' });
} catch (e) { } catch (e) {
console.error('[scheduler] run-now', e); console.error('[scheduler] run-now', e);
const msg = e?.message || String(e);
try {
networkMapScheduler.pushLog(`Ошибка запуска: ${msg}`);
} catch (_) {}
return sendError(res, 500, 'Не удалось запустить', 'E_SCHEDULER'); return sendError(res, 500, 'Не удалось запустить', 'E_SCHEDULER');
} }
} }
+21 -7
View File
@@ -164,10 +164,12 @@ async function runWithOnePerKey(tasks, getKey) {
* @param {object} opts - { baseUrl, runPing, runSpeedTest, log } * @param {object} opts - { baseUrl, runPing, runSpeedTest, log }
*/ */
async function runJob(opts) { async function runJob(opts) {
const { baseUrl, runPing = true, runSpeedTest = true, log = (msg) => logBuffer.push(msg) } = opts; const { baseUrl, runPing = true, runSpeedTest = true, log = (msg) => logBuffer.push(msg), trigger = 'scheduled' } = opts;
const pingMap = {}; const pingMap = {};
const speedMap = {}; const speedMap = {};
log(trigger === 'manual' ? '--- Ручной запуск ---' : '--- Запуск по расписанию ---');
try { try {
const { connections, servers } = await buildConnections(); const { connections, servers } = await buildConnections();
if (connections.length === 0) { if (connections.length === 0) {
@@ -201,12 +203,14 @@ async function runJob(opts) {
target: c.internalFromTo, target: c.internalFromTo,
gatewayIp: c.internalFromTo, gatewayIp: c.internalFromTo,
count: 3, count: 3,
forceRefresh: true,
}), }),
}); });
const data = await res.json().catch(() => ({})); const data = await res.json().catch(() => ({}));
const ms = typeof data?.avgMs === 'number' ? Math.round(data.avgMs) : null; const ms = typeof data?.avgMs === 'number' ? Math.round(data.avgMs) : null;
pingMap[ekey] = ms; pingMap[ekey] = ms;
log(`Пинг ${from}${to}: ${ms != null ? ms + ' ms' : 'ошибка'}`); const errMsg = !res.ok ? (data?.message || `HTTP ${res.status}`) : null;
log(`Пинг ${from}${to}: ${ms != null ? ms + ' ms' : errMsg || 'ошибка'}`);
return ms; return ms;
} catch (e) { } catch (e) {
pingMap[ekey] = null; pingMap[ekey] = null;
@@ -226,12 +230,14 @@ async function runJob(opts) {
target: c.internalToFrom, target: c.internalToFrom,
gatewayIp: c.internalToFrom, gatewayIp: c.internalToFrom,
count: 3, count: 3,
forceRefresh: true,
}), }),
}); });
const data = await res.json().catch(() => ({})); const data = await res.json().catch(() => ({}));
const ms = typeof data?.avgMs === 'number' ? Math.round(data.avgMs) : null; const ms = typeof data?.avgMs === 'number' ? Math.round(data.avgMs) : null;
pingMap[ekey] = ms; pingMap[ekey] = ms;
log(`Пинг ${to}${from}: ${ms != null ? ms + ' ms' : 'ошибка'}`); const errMsg2 = !res.ok ? (data?.message || `HTTP ${res.status}`) : null;
log(`Пинг ${to}${from}: ${ms != null ? ms + ' ms' : errMsg2 || 'ошибка'}`);
return ms; return ms;
} catch (e) { } catch (e) {
pingMap[ekey] = null; pingMap[ekey] = null;
@@ -255,11 +261,12 @@ async function runJob(opts) {
body: JSON.stringify({ body: JSON.stringify({
serverId: c.speedTestServerId, serverId: c.speedTestServerId,
interfaceName: c.interfaceName, interfaceName: c.interfaceName,
forceRefresh: true,
}), }),
signal: (() => { signal: (() => {
const c = new AbortController(); const ac = new AbortController();
setTimeout(() => c.abort(), 120000); setTimeout(() => ac.abort(), 120000);
return c.signal; return ac.signal;
})(), })(),
}); });
const data = await res.json().catch(() => ({})); const data = await res.json().catch(() => ({}));
@@ -276,7 +283,8 @@ async function runJob(opts) {
return speedMap[key]; return speedMap[key];
} }
speedMap[key] = null; speedMap[key] = null;
log(`Скорость ${c.interfaceName}: нет данных`); const speedErr = !res.ok ? (data?.message || `HTTP ${res.status}`) : 'нет данных';
log(`Скорость ${c.interfaceName}: ${speedErr}`);
return null; return null;
} catch (e) { } catch (e) {
speedMap[key] = null; speedMap[key] = null;
@@ -402,6 +410,11 @@ function setLogMaxLines(n) {
logBuffer.setMaxLines(num); logBuffer.setMaxLines(num);
} }
/** Добавить строку в лог (для вывода ошибок из роутов) */
function pushLog(msg) {
logBuffer.push(msg);
}
module.exports = { module.exports = {
runJob, runJob,
initNetworkMapScheduler, initNetworkMapScheduler,
@@ -409,6 +422,7 @@ module.exports = {
getLogs, getLogs,
getLogMaxLines, getLogMaxLines,
setLogMaxLines, setLogMaxLines,
pushLog,
getSettingsFromUiSettings, getSettingsFromUiSettings,
loadUiSettings: loadUiSettings, loadUiSettings: loadUiSettings,
buildConnections, buildConnections,