Remove outdated documentation files for companies and migration guide; implement server session management features including server assignment and session status updates; enhance database schema for servers and server sessions with new fields and validation; add auto-assign functionality for unassigned sessions.

This commit is contained in:
2025-10-06 15:59:55 +05:00
parent 9e4bc7b0f8
commit a49129f643
16 changed files with 2332 additions and 483 deletions
+397
View File
@@ -0,0 +1,397 @@
# Session Server
Сессионный сервер для автоматической регистрации на основном API сервере.
## Описание
Session Server - это приложение, которое автоматически регистрируется на основном сервере (`stream.graff.tech`) и периодически обновляет свою информацию. Это позволяет основному серверу знать о доступных сессионных серверах для распределения нагрузки.
## Возможности
- 🚀 Автоматическая регистрация при запуске
- 🔄 Периодическое обновление информации о сервере (по умолчанию каждые 30 секунд после завершения предыдущего запроса)
- 🎮 Автоматическое определение и обновление свободной GPU памяти через nvidia-smi (по умолчанию каждую секунду после завершения предыдущего запроса)
- 🎯 Автоматическое управление игровыми сессиями
- Запуск приложений для сессий со статусом "starting"
- Остановка приложений для сессий со статусом "ending"
- Отслеживание PID запущенных процессов
- Автоматическое обновление статусов сессий на главном сервере
- 🌐 Автоматическое определение локального IP адреса
- 💻 Автоматическое определение hostname
- ⚙️ Гибкая конфигурация через переменные окружения
- 🔁 Автоматические повторные попытки при ошибках
- 📝 Подробное логирование
- ⚡ Защита от наложения запросов для всех операций (рекурсивный вызов через setTimeout)
## Установка
```bash
# Установка зависимостей
bun install
```
## Конфигурация
Создайте файл `.env` в корне проекта на основе `.env.example`:
```bash
# 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 автоматически управляет игровыми сессиями на этом сервере:
### Как это работает
1. **Проверка сессий**: Каждую секунду (или согласно `SESSION_CHECK_INTERVAL_MS`) сервер запрашивает у основного API список сессий для этого сервера
2. **Запуск приложений**: Для сессий со статусом `starting`:
- ⏰ Проверяется время `startAt` - приложение запускается только если это время уже наступило
- **Timezone**: Все время хранится в UTC, сравнение корректно работает независимо от часового пояса сервера
- Запланированные сессии (с будущим `startAt`) логируются с информацией о времени до запуска
- 🎯 **Централизованное назначение сервера** (для stream-сессий):
- **Main server** автоматически назначает серверы каждые 5 секунд
- Выбирается сервер с максимальной свободной GPU памятью
- Учитываются требования приложения к GPU памяти (`gpuLimitMb`)
- Session-server просто проверяет, что сессия назначена ему
- Запускается соответствующее приложение
- Отслеживается PID процесса
- Статус сессии обновляется на `started` на главном сервере
3. **Остановка приложений**: Для сессий со статусом `ending`:
- Используется `taskkill /pid {PID} /T /F` для завершения всего дерева процессов
- `/T` - завершает указанный процесс и ВСЕ дочерние процессы
- `/F` - принудительное завершение
- Решает проблему с UE5 и другими приложениями, создающими дочерние процессы
- Статус сессии обновляется на `ended` на главном сервере
4. **Автоматическая очистка**: Процессы для неактивных сессий автоматически останавливаются
### 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 (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)
Если приложение запускается и сразу завершается с ошибкой, см. подробное руководство по диагностике:
- **[TROUBLESHOOTING.md](./TROUBLESHOOTING.md)**
### Новые возможности логирования
После обновления вы увидите:
- 🔴 **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 корректно работает с разными часовыми поясами:
### Как это работает
1. **База данных**: PostgreSQL хранит все timestamp с timezone в UTC
2. **API**: Основной сервер возвращает время в формате ISO 8601 с timezone (например, `2025-10-06T10:00:00.000Z`)
3. **Session Server**: JavaScript автоматически парсит ISO 8601 строки в UTC
4. **Сравнение**: Все сравнения времени происходят в UTC, независимо от локального часового пояса сервера
### Миграция базы данных
⚠️ **Важно**: Если вы обновляете существующую систему, необходимо выполнить миграцию для добавления timezone в поля `startAt` и `endAt`:
```bash
# Из директории 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 режим
```bash
bun run dev
```
### Production режим
```bash
# Собрать проект
bun run build
# Запустить собранное приложение
bun run start
```
## Примеры использования
### Stream сервер в России (демо)
```env
API_URL=https://api.stream.graff.tech
SERVER_TYPE=stream
SERVER_LOCATION=ru1
SERVER_TIER=demo
REGISTER_INTERVAL_MS=30000
```
### Stream сервер в ОАЭ (продакшн)
```env
API_URL=https://api.stream.graff.tech
SERVER_TYPE=stream
SERVER_LOCATION=uae1
SERVER_TIER=prod
REGISTER_INTERVAL_MS=30000
```
### Local сервер для филиала
```env
API_URL=https://api.stream.graff.tech
SERVER_TYPE=local
BRANCH_ID=123e4567-e89b-12d3-a456-426614174000
REGISTER_INTERVAL_MS=60000
```
## Логирование
Сервер выводит подробную информацию о своей работе:
```text
============================================================
🚀 Запуск сессионного сервера
============================================================
Конфигурация:
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`
- При отсутствии обязательных полей сервер завершит работу с критической ошибкой
- **Сетевые ошибки**: Автоматические повторные попытки (до 3 раз)
- **Таймауты**: 10 секунд на запрос
- **Коды ошибок**: Повторная отправка при временных ошибках сервера (408, 429, 500, 502, 503, 504)
- **Ошибки GPU**: Если `nvidia-smi` недоступен или возвращает некорректные данные, сервер завершит работу с критической ошибкой
- **Критические ошибки**: Подробное логирование с завершением работы
## Архитектура
```text
┌──────────────────────────────────┐
│ 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. Возврат данных │
└──────────────────────────────────┘
```
## Разработка
### Структура проекта
```text
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