feat(NetworkMapScheduler): add next scheduled run time to settings response and update frontend to display next run time
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m36s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m36s
This commit is contained in:
@@ -32,7 +32,8 @@ async function getNetworkMapSchedulerSettings(req, res) {
|
||||
try {
|
||||
const ui = await readUiSettings();
|
||||
const settings = networkMapScheduler.getSettingsFromUiSettings(ui);
|
||||
return res.json(settings);
|
||||
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');
|
||||
|
||||
@@ -320,6 +320,8 @@ async function writeCache(pingMap, speedMap) {
|
||||
}
|
||||
|
||||
let schedulerTimer = null;
|
||||
/** Время последнего запуска по расписанию (для расчёта следующего) */
|
||||
let lastScheduledRunAt = null;
|
||||
|
||||
function getSettingsFromUiSettings(uiSettings) {
|
||||
return {
|
||||
@@ -341,6 +343,7 @@ function initNetworkMapScheduler(logger, port) {
|
||||
const baseUrl = `http://127.0.0.1:${port}`;
|
||||
|
||||
async function tick() {
|
||||
lastScheduledRunAt = Date.now();
|
||||
let uiSettings;
|
||||
try {
|
||||
const raw = await readS3TextObject(UI_SETTINGS_KEY).catch(() => ({ body: '{}' }));
|
||||
@@ -418,6 +421,18 @@ function pushLog(msg) {
|
||||
logBuffer.push(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Время следующего запуска по расписанию (timestamp или null если выключено).
|
||||
* @param {object} settings - результат getSettingsFromUiSettings()
|
||||
* @returns {number|null}
|
||||
*/
|
||||
function getNextRunAt(settings) {
|
||||
if (!settings || !settings.enabled) return null;
|
||||
const intervalMs = (settings.intervalMinutes || DEFAULT_INTERVAL_MINUTES) * 60 * 1000;
|
||||
const from = lastScheduledRunAt || Date.now();
|
||||
return from + intervalMs;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
runJob,
|
||||
initNetworkMapScheduler,
|
||||
@@ -427,6 +442,7 @@ module.exports = {
|
||||
setLogMaxLines,
|
||||
pushLog,
|
||||
getSettingsFromUiSettings,
|
||||
getNextRunAt,
|
||||
loadUiSettings: loadUiSettings,
|
||||
buildConnections,
|
||||
LogBuffer,
|
||||
|
||||
@@ -278,31 +278,8 @@ export default function NetworkMapDashboard() {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && servers.length > 0 && connections.length > 0) {
|
||||
const cacheMaxAgeMs = Math.max((pingCacheSeconds || 60) * 1000, 60 * 1000);
|
||||
if (cacheAppliedAtRef.current && Date.now() - cacheAppliedAtRef.current < cacheMaxAgeMs) {
|
||||
return;
|
||||
}
|
||||
requestPings();
|
||||
}
|
||||
return () => {
|
||||
pingAbortRef.current = true;
|
||||
};
|
||||
}, [loading, connections.length, pingCacheSeconds, requestPings]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && connections.length > 0) {
|
||||
const cacheMaxAgeMs = Math.max((pingCacheSeconds || 60) * 1000, 60 * 1000);
|
||||
if (cacheAppliedAtRef.current && Date.now() - cacheAppliedAtRef.current < cacheMaxAgeMs) {
|
||||
return;
|
||||
}
|
||||
requestSpeeds();
|
||||
}
|
||||
return () => {
|
||||
speedAbortRef.current = true;
|
||||
};
|
||||
}, [loading, connections.length, pingCacheSeconds, requestSpeeds]);
|
||||
// Пинг и скорость не запускаются автоматически при открытии карты (даже если кеш просрочен).
|
||||
// Обновление только по кнопкам «Пинг» и «Скорость» или по планировщику.
|
||||
|
||||
const handleRefreshPings = () => {
|
||||
requestPings();
|
||||
|
||||
@@ -23,6 +23,7 @@ export default function NetworkMapSchedulerPage() {
|
||||
runSpeedTest: true,
|
||||
logMaxLines: 500,
|
||||
});
|
||||
const [nextRunAt, setNextRunAt] = useState(null);
|
||||
const [logs, setLogs] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
@@ -42,6 +43,7 @@ export default function NetworkMapSchedulerPage() {
|
||||
runSpeedTest: data.runSpeedTest !== false,
|
||||
logMaxLines: Math.max(LOG_LINES_MIN, Math.min(LOG_LINES_MAX, Number(data.logMaxLines) || 500)),
|
||||
});
|
||||
setNextRunAt(typeof data.nextRunAt === 'number' ? data.nextRunAt : null);
|
||||
} catch (e) {
|
||||
setError(e?.response?.data?.message || e?.message || 'Не удалось загрузить настройки');
|
||||
}
|
||||
@@ -72,6 +74,12 @@ export default function NetworkMapSchedulerPage() {
|
||||
return () => clearInterval(t);
|
||||
}, [fetchLogs]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!settings.enabled || !nextRunAt) return;
|
||||
const t = setInterval(fetchSettings, 60 * 1000);
|
||||
return () => clearInterval(t);
|
||||
}, [settings.enabled, nextRunAt, fetchSettings]);
|
||||
|
||||
useEffect(() => {
|
||||
if (autoScroll && logEndRef.current) {
|
||||
logEndRef.current.scrollIntoView({ behavior: 'smooth' });
|
||||
@@ -182,6 +190,11 @@ export default function NetworkMapSchedulerPage() {
|
||||
<span className="form-check-label">Включить планировщик</span>
|
||||
</label>
|
||||
<div className="form-hint">Периодически обновлять пинг и скорость по связям из «Сетевые настройки»</div>
|
||||
{settings.enabled && nextRunAt != null && (
|
||||
<div className="mt-2 text-muted small">
|
||||
Следующий запуск: {new Date(nextRunAt).toLocaleString('ru-RU', { dateStyle: 'short', timeStyle: 'medium' })}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
|
||||
Reference in New Issue
Block a user