- Introduced SessionInfoFloat component to display session details when a session is active. - Updated session server logic to automatically transition sessions to "ending" status when their end time is reached. - Improved process termination handling with enhanced error checking and fallback mechanisms. - Refactored application stop logic to handle multiple processes more efficiently and added timeout management for process termination.
Session Server
Сессионный сервер для автоматической регистрации на основном API сервере.
Описание
Session Server - это приложение, которое автоматически регистрируется на основном сервере (stream.graff.tech) и периодически обновляет свою информацию. Это позволяет основному серверу знать о доступных сессионных серверах для распределения нагрузки.
Возможности
- 🚀 Автоматическая регистрация при запуске
- 🔄 Периодическое обновление информации о сервере (по умолчанию каждые 30 секунд после завершения предыдущего запроса)
- 🎮 Автоматическое определение и обновление свободной GPU памяти через nvidia-smi (по умолчанию каждую секунду после завершения предыдущего запроса)
- 🎯 Автоматическое управление игровыми сессиями
- Запуск приложений для сессий со статусом "starting"
- Остановка приложений для сессий со статусом "ending"
- Отслеживание PID запущенных процессов
- Автоматическое обновление статусов сессий на главном сервере
- 🌐 Автоматическое определение локального IP адреса
- 💻 Автоматическое определение hostname
- ⚙️ Гибкая конфигурация через переменные окружения
- 🔁 Автоматические повторные попытки при ошибках
- 📝 Подробное логирование
- ⚡ Защита от наложения запросов для всех операций (рекурсивный вызов через setTimeout)
Установка
# Установка зависимостей
bun install
Конфигурация
Создайте файл .env в корне проекта на основе .env.example:
# URL основного API сервера
API_URL=http://localhost:3000
# Тип сервера: stream или local
SERVER_TYPE=stream
# Расположение сервера (ОБЯЗАТЕЛЬНО для stream серверов)
# Возможные значения: ru1, uae1
SERVER_LOCATION=ru1
# Уровень сервера (только для stream серверов)
# Возможные значения: demo, prod
SERVER_TIER=demo
# ID филиала (ОБЯЗАТЕЛЬНО для local серверов)
BRANCH_ID=00000000-0000-0000-0000-000000000000
# Локальный IP адрес (опционально, определяется автоматически)
# LOCAL_IP=192.168.1.100
# Hostname сервера (опционально, определяется автоматически)
# HOSTNAME=my-session-server
# Интервал регистрации в миллисекундах (по умолчанию 30000 = 30 секунд)
REGISTER_INTERVAL_MS=30000
# Интервал обновления GPU памяти в миллисекундах (по умолчанию 1000 = 1 секунда)
GPU_UPDATE_INTERVAL_MS=1000
# Интервал проверки сессий в миллисекундах (по умолчанию 5000 = 5 секунд)
SESSION_CHECK_INTERVAL_MS=5000
Переменные окружения
| Переменная | Описание | Обязательна | По умолчанию |
|---|---|---|---|
API_URL |
URL основного API сервера | Нет | http://localhost:3000 |
SERVER_TYPE |
Тип сервера (stream или local) |
Нет | stream |
SERVER_LOCATION |
Расположение (ru1, uae1) - обязательно для stream |
Да (для stream) | - |
SERVER_TIER |
Уровень (demo, prod) - только для stream |
Нет | demo (для stream) |
BRANCH_ID |
ID филиала - обязательно для local |
Да (для local) | - |
LOCAL_IP |
Локальный IP адрес | Нет | Определяется автоматически |
HOSTNAME |
Hostname сервера | Нет | Определяется автоматически |
REGISTER_INTERVAL_MS |
Интервал регистрации в мс | Нет | 30000 |
GPU_UPDATE_INTERVAL_MS |
Интервал обновления GPU памяти в мс | Нет | 1000 |
SESSION_CHECK_INTERVAL_MS |
Интервал проверки сессий в мс | Нет | 5000 |
Примечание: Свободная память GPU (gpuFreeMb) автоматически определяется через nvidia-smi при каждой регистрации и обновляется каждую секунду (или согласно GPU_UPDATE_INTERVAL_MS) после завершения предыдущего запроса. Это предотвращает наложение запросов. Если nvidia-smi недоступен, сервер завершит работу с ошибкой.
Управление сессиями
Session Server автоматически управляет игровыми сессиями на этом сервере:
Как это работает
- Проверка сессий: Каждую секунду (или согласно
SESSION_CHECK_INTERVAL_MS) сервер запрашивает у основного API список сессий для этого сервера - Проверка времени окончания: Для активных сессий (
startedилиstarting):- ⏰ Проверяется время
endAt- если оно наступило, сессия автоматически переводится в статусending - Timezone: Все время хранится в UTC, сравнение корректно работает независимо от часового пояса сервера
- По умолчанию сессии создаются с временем окончания +30 минут от момента создания
- Автоматическое завершение гарантирует, что сессии не будут работать бесконечно
- ⏰ Проверяется время
- Запуск приложений: Для сессий со статусом
starting:- ⏰ Проверяется время
startAt- приложение запускается только если это время уже наступило - Timezone: Все время хранится в UTC, сравнение корректно работает независимо от часового пояса сервера
- Запланированные сессии (с будущим
startAt) логируются с информацией о времени до запуска - 🎯 Централизованное назначение сервера (для stream-сессий):
- Main server автоматически назначает серверы каждые 5 секунд
- Выбирается сервер с максимальной свободной GPU памятью
- Учитываются требования приложения к GPU памяти (
gpuLimitMb) - Session-server просто проверяет, что сессия назначена ему
- Запускается соответствующее приложение
- Отслеживается PID процесса
- Статус сессии обновляется на
startedна главном сервере
- ⏰ Проверяется время
- Остановка приложений: Для сессий со статусом
ending:- Используется
taskkill /pid {PID} /T /Fдля завершения всего дерева процессов /T- завершает указанный процесс и ВСЕ дочерние процессы/F- принудительное завершение- Решает проблему с UE5 и другими приложениями, создающими дочерние процессы
- Статус сессии обновляется на
endedна главном сервере
- Используется
- Автоматическая очистка: Процессы для неактивных сессий автоматически останавливаются
API endpoints для управления сессиями
Session Server взаимодействует с основным сервером через следующие endpoints:
GET /servers/:id/sessions- получить список сессий для сервераPATCH /sessions/:id/status- обновить статус сессии (публичный endpoint)
Запуск приложений
Session Server автоматически запускает .exe приложения по стандартному пути:
C:\apps\{appName}\{appName}.exe
Где {appName} - это значение поля name из таблицы apps.
Структура директорий
Все приложения должны быть размещены в следующей структуре:
C:\apps\
├── minecraft\
│ └── minecraft.exe
├── fortnite\
│ └── fortnite.exe
└── cyberpunk\
└── cyberpunk.exe
Особенности запуска и остановки
- ✅ Автоматическая проверка существования exe файла
- ✅ Рабочая директория устанавливается в папку приложения (
C:\apps\{appName}\) - ✅ Окно консоли скрывается (
windowsHide: true) - ✅ PID процесса отслеживается и передается на main server
- ✅ Автоматическое обновление статуса при завершении процесса
- ✅ Корректное завершение дочерних процессов - использует
taskkill /Tдля завершения всего дерева процессов - ✅ Решает проблему с UE5 приложениями, которые создают множественные процессы
Логи запуска
[2025-10-06T10:00:00.000Z] 🚀 Запуск приложения "minecraft" для сессии abc-123
[2025-10-06T10:00:00.050Z] 📂 Путь к приложению: C:\apps\minecraft\minecraft.exe
[2025-10-06T10:00:01.000Z] ✅ Приложение запущено с PID 12345
[2025-10-06T10:00:01.100Z] ✅ Статус сессии abc-123 обновлен на "started"
Обработка ошибок
Если exe файл не найден:
❌ Файл приложения не найден: C:\apps\minecraft\minecraft.exe. Убедитесь, что приложение установлено.
Примеры логов
Запланированная сессия:
[2025-10-06T10:00:00.000Z] ⏰ Сессия 123e4567-e89b-12d3-a456-426614174000 (minecraft) запланирована через 120 сек
Запуск сессии:
[2025-10-06T10:02:00.000Z] 🚀 Запуск приложения "minecraft" для сессии 123e4567-e89b-12d3-a456-426614174000
[2025-10-06T10:02:01.000Z] ✅ Приложение запущено с PID 12345
[2025-10-06T10:02:01.100Z] ✅ Статус сессии 123e4567-e89b-12d3-a456-426614174000 обновлен на "started"
Автоматическое завершение по истечении времени:
[2025-10-06T10:32:00.000Z] ⏰ Время сессии 123e4567-e89b-12d3-a456-426614174000 (minecraft) истекло, завершение...
[2025-10-06T10:32:00.100Z] ✅ Статус сессии 123e4567-e89b-12d3-a456-426614174000 обновлен на "ending"
Остановка сессии:
[2025-10-06T10:32:00.000Z] 🛑 Остановка приложения для сессии 123e4567-e89b-12d3-a456-426614174000 (PID: 12345)
[2025-10-06T10:32:00.500Z] ✅ Дерево процессов для PID 12345 успешно завершено
[2025-10-06T10:32:00.600Z] ✅ Приложение и все дочерние процессы остановлены для сессии 123e4567-e89b-12d3-a456-426614174000
[2025-10-06T10:32:00.700Z] ✅ Статус сессии 123e4567-e89b-12d3-a456-426614174000 обновлен на "ended"
Отладка проблем (Troubleshooting)
Если приложение запускается и сразу завершается с ошибкой, см. подробное руководство по диагностике:
Новые возможности логирования
После обновления вы увидите:
- 🔴 STDERR логи для диагностики ошибок приложений
- 📊 Счётчик активных процессов при запуске/завершении
- ⚠️ Детальная информация о кодах выхода и сигналах
Пример логов с ошибкой:
[10:51:56.498Z] 🚀 Запуск приложения "ShishimGorka" для сессии abc (активных процессов: 1)
[10:51:56.563Z] ✅ Приложение запущено с PID 84112 (всего активных: 2)
[10:51:57.500Z] 🔴 STDERR [abc]: Error: Port 8888 is already in use
[10:51:57.894Z] 🛑 Приложение для сессии abc завершилось с кодом 1
[10:51:57.894Z] ⚠️ Приложение завершилось с ошибкой! Код выхода: 1
Работа с часовыми поясами (Timezone)
Session Server корректно работает с разными часовыми поясами:
Как это работает
- База данных: PostgreSQL хранит все timestamp с timezone в UTC
- API: Основной сервер возвращает время в формате ISO 8601 с timezone (например,
2025-10-06T10:00:00.000Z) - Session Server: JavaScript автоматически парсит ISO 8601 строки в UTC
- Сравнение: Все сравнения времени происходят в UTC, независимо от локального часового пояса сервера
Миграция базы данных
⚠️ Важно: Если вы обновляете существующую систему, необходимо выполнить миграцию для добавления timezone в поля startAt и endAt:
# Из директории server/
psql -d $DATABASE_URL -f timezone_migration.sql
См. server/TIMEZONE_MIGRATION.md для подробностей.
Примеры
Если сервер в России создаёт сессию на 14:00 по московскому времени (UTC+3):
- В БД сохранится:
2025-10-06T11:00:00.000Z(UTC) - Сервер в ОАЭ (UTC+4) увидит: 15:00 по местному времени
- Session Server запустит приложение ровно в 11:00 UTC, независимо от локального времени
Запуск
Development режим
bun run dev
Production режим
# Собрать проект
bun run build
# Запустить собранное приложение
bun run start
Примеры использования
Stream сервер в России (демо)
API_URL=https://api.stream.graff.tech
SERVER_TYPE=stream
SERVER_LOCATION=ru1
SERVER_TIER=demo
REGISTER_INTERVAL_MS=30000
Stream сервер в ОАЭ (продакшн)
API_URL=https://api.stream.graff.tech
SERVER_TYPE=stream
SERVER_LOCATION=uae1
SERVER_TIER=prod
REGISTER_INTERVAL_MS=30000
Local сервер для филиала
API_URL=https://api.stream.graff.tech
SERVER_TYPE=local
BRANCH_ID=123e4567-e89b-12d3-a456-426614174000
REGISTER_INTERVAL_MS=60000
Логирование
Сервер выводит подробную информацию о своей работе:
============================================================
🚀 Запуск сессионного сервера
============================================================
Конфигурация:
API URL: http://localhost:3000
Hostname: DESKTOP-ABC123
Local IP: 192.168.1.100
Type: stream
GPU Free MB: 8192 (читается из nvidia-smi)
Location: ru1
Tier: demo
Register Interval: 30000ms
GPU Update Interval: 1000ms
============================================================
[2025-10-06T12:00:00.000Z] Регистрация сервера...
Данные: {
"localIp": "192.168.1.100",
"hostname": "DESKTOP-ABC123",
"type": "stream",
"gpuFreeMb": 8192,
"location": "ru1",
"tier": "demo"
}
[2025-10-06T12:00:00.123Z] ✅ Сервер успешно зарегистрирован
ID сервера: 123e4567-e89b-12d3-a456-426614174000
[2025-10-06T12:00:01.000Z] 🎮 GPU память обновлена: 8150 MB
[2025-10-06T12:00:02.000Z] 🎮 GPU память обновлена: 8120 MB
[2025-10-06T12:00:03.000Z] 🎮 GPU память обновлена: 8100 MB
Обработка ошибок
Сервер автоматически обрабатывает ошибки:
- Валидация конфигурации:
- Stream-серверы: обязательно должен быть указан
SERVER_LOCATION - Local-серверы: обязательно должен быть указан
BRANCH_ID - При отсутствии обязательных полей сервер завершит работу с критической ошибкой
- Stream-серверы: обязательно должен быть указан
- Сетевые ошибки: Автоматические повторные попытки (до 3 раз)
- Таймауты: 10 секунд на запрос
- Коды ошибок: Повторная отправка при временных ошибках сервера (408, 429, 500, 502, 503, 504)
- Ошибки GPU: Если
nvidia-smiнедоступен или возвращает некорректные данные, сервер завершит работу с критической ошибкой - Критические ошибки: Подробное логирование с завершением работы
Архитектура
┌──────────────────────────────────┐
│ Session Server │
│ │
│ Регистрация (рекурсивно): │
│ 1. Определение IP │
│ 2. Определение hostname │
│ 3. Запрос GPU (nvidia-smi) │
│ 4. POST /servers/register │
│ 5. setTimeout → повтор (30s) │
│ │
│ Обновление GPU (рекурсивно): │
│ 1. Запрос GPU (nvidia-smi) │
│ 2. PATCH /servers/:id/gpu │
│ 3. setTimeout → повтор (1s) │
└──────────┬───────────────────────┘
│
│ HTTP Requests
│
▼
┌──────────────────────────────────┐
│ Main API Server │
│ │
│ 1. Проверка по hostname │
│ 2. Создание/обновление │
│ 3. Обновление GPU памяти │
│ 4. Возврат данных │
└──────────────────────────────────┘
Разработка
Структура проекта
session-server/
├── src/
│ └── index.ts # Основной файл приложения
├── dist/ # Собранное приложение
├── package.json
├── tsconfig.json
├── bun.build.ts # Конфигурация сборки
└── README.md
Требования
- Bun >= 1.0
- Node.js >= 18 (опционально)
- TypeScript >= 5.0
- NVIDIA GPU с установленным
nvidia-smi(обязательно)
Лицензия
MIT