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
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m44s
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user