Update package dependencies and enhance session management features

- Added react-hot-toast for improved user notifications in the application.
- Updated baseline-browser-mapping to version 2.9.2.
- Introduced maxInstances property in Session and App schemas to manage concurrent instances.
- Refactored server session handling to enforce instance limits and improve error messaging.
- Removed GPU memory management from server registration and session assignment logic for cleaner implementation.
- Enhanced error handling in session management with localized messages for better user experience.
This commit is contained in:
2025-12-05 18:04:01 +05:00
parent 775ba52cd0
commit c384087f38
13 changed files with 234 additions and 254 deletions
+2 -92
View File
@@ -40,10 +40,6 @@ const REGISTER_INTERVAL_MS = parseInt(
process.env.REGISTER_INTERVAL_MS || "30000",
10
); // 30 секунд по умолчанию
const GPU_UPDATE_INTERVAL_MS = parseInt(
process.env.GPU_UPDATE_INTERVAL_MS || "1000",
10
); // 1 секунда по умолчанию
const SESSION_CHECK_INTERVAL_MS = parseInt(
process.env.SESSION_CHECK_INTERVAL_MS || "1000",
10
@@ -68,7 +64,6 @@ interface ServerRegistrationData {
localIp: string;
hostname: string;
type: "stream" | "local";
gpuFreeMb: number;
branchId?: string;
location?: "ru1" | "uae1";
tier?: "demo" | "prod";
@@ -80,7 +75,6 @@ interface ServerRegistrationResponse {
localIp: string;
hostname: string;
type: "stream" | "local";
gpuFreeMb: number;
branchId?: string;
location?: "ru1" | "uae1";
tier?: "demo" | "prod";
@@ -112,6 +106,7 @@ interface SessionData {
title: string;
gpuLimitMb: number | null;
psVersion: number | null;
maxInstances: number | null;
};
user: {
id: string;
@@ -177,49 +172,6 @@ function findFreePort(
});
}
/**
* Получить свободную память GPU через nvidia-smi
* Возвращает количество свободной памяти в МБ
* Выбрасывает ошибку, если не удалось получить данные
*/
function getGpuFreeMb(): number {
try {
// Выполняем nvidia-smi с форматом вывода только свободной памяти
// --query-gpu=memory.free - запрашиваем свободную память
// --format=csv,noheader,nounits - CSV формат без заголовков и единиц измерения
const output = execSync(
"nvidia-smi --query-gpu=memory.free --format=csv,noheader,nounits",
{
encoding: "utf-8",
timeout: 5000, // 5 секунд таймаут
windowsHide: true, // Скрыть окно консоли на Windows
stdio: "pipe", // Перенаправить вывод в pipe вместо создания нового окна
}
);
// Парсим вывод (может быть несколько GPU, берём первый)
const lines = output.trim().split("\n");
if (lines.length > 0 && lines[0]) {
const freeMb = parseInt(lines[0].trim(), 10);
if (!isNaN(freeMb) && freeMb >= 0) {
return freeMb;
}
}
throw new Error("Не удалось распарсить вывод nvidia-smi");
} catch (error) {
console.error(
`[${new Date().toISOString()}] ❌ Критическая ошибка при получении данных GPU:`,
error instanceof Error ? error.message : error
);
throw new Error(
`Невозможно получить данные о GPU через nvidia-smi: ${
error instanceof Error ? error.message : String(error)
}`
);
}
}
/**
* Регистрация сервера на главном сервере
*/
@@ -243,14 +195,10 @@ async function registerServer(isRecursive: boolean = false): Promise<void> {
// Установить tier по умолчанию для stream-серверов
const tier = SERVER_TYPE === "stream" && !SERVER_TIER ? "demo" : SERVER_TIER;
// Получаем актуальное значение свободной GPU памяти
const gpuFreeMb = getGpuFreeMb();
const registrationData: ServerRegistrationData = {
localIp: LOCAL_IP,
hostname: HOSTNAME,
type: SERVER_TYPE,
gpuFreeMb: gpuFreeMb,
branchId: BRANCH_ID,
location: SERVER_LOCATION,
tier: tier,
@@ -288,9 +236,8 @@ async function registerServer(isRecursive: boolean = false): Promise<void> {
);
}
// При первом запуске запускаем обновление GPU и проверку сессий после успешной регистрации
// При первом запуске запускаем проверку сессий после успешной регистрации
if (!isRecursive && SERVER_ID) {
updateGpuMemory();
checkSessions();
}
} catch (error: unknown) {
@@ -313,40 +260,6 @@ async function registerServer(isRecursive: boolean = false): Promise<void> {
setTimeout(() => registerServer(true), REGISTER_INTERVAL_MS);
}
/**
* Обновить информацию о свободной памяти GPU на сервере
*/
async function updateGpuMemory(): Promise<void> {
try {
// Получаем актуальное значение свободной GPU памяти
const gpuFreeMb = getGpuFreeMb();
await got.patch(`${API_URL}/servers/${SERVER_ID}/gpu`, {
json: { gpuFreeMb },
timeout: {
request: 5000, // 5 секунд таймаут
},
retry: {
limit: 2,
methods: ["PATCH"],
statusCodes: [408, 429, 500, 502, 503, 504],
},
});
console.log(
`[${new Date().toISOString()}] 🎮 GPU память обновлена: ${gpuFreeMb} MB`
);
} catch (error: unknown) {
console.error(
`[${new Date().toISOString()}] ❌ Ошибка обновления GPU памяти:`,
error instanceof RequestError ? error.message : error
);
}
// Планируем следующее обновление после завершения текущего
setTimeout(() => updateGpuMemory(), GPU_UPDATE_INTERVAL_MS);
}
/**
* Получить сессии для этого сервера
*/
@@ -978,18 +891,15 @@ async function main() {
console.log(` Hostname: ${HOSTNAME}`);
console.log(` Local IP: ${LOCAL_IP}`);
console.log(` Type: ${SERVER_TYPE}`);
console.log(` GPU Free MB: ${getGpuFreeMb()} (читается из nvidia-smi)`);
if (SERVER_LOCATION) console.log(` Location: ${SERVER_LOCATION}`);
if (SERVER_TIER) console.log(` Tier: ${SERVER_TIER}`);
if (BRANCH_ID) console.log(` Branch ID: ${BRANCH_ID}`);
console.log(` Register Interval: ${REGISTER_INTERVAL_MS}ms`);
console.log(` GPU Update Interval: ${GPU_UPDATE_INTERVAL_MS}ms`);
console.log(` Session Check Interval: ${SESSION_CHECK_INTERVAL_MS}ms`);
console.log("=".repeat(60));
// Запуск рекурсивной регистрации
// Использует setTimeout вместо setInterval, чтобы избежать наложения запросов
// После первой успешной регистрации запускается обновление GPU
await registerServer();
}