Files
hockey_new/docs/ARCHITECTURE.md

69 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Архитектура
## Модули
| Каталог | Назначение |
| --- | --- |
| `hockey_data/` | Stat2TV, PostgreSQL, матч, статистика, роли, mapping и Agent bridge |
| `ui_builder/` | Действующий runtime/редактор UI и активные статические ресурсы |
| `broadcast_settings/` | Переносимые настройки команд и vMix JSON |
| `khl_site/` | Карточки КХЛ, карьера, обновления и локальные данные |
| `agent/` | Windows Agent и исходники Go |
| `settings/local/` | Активная конфигурация UI, таймеров, обновлений и восстановление |
| `tests/` | Регрессии серверной логики и браузерных функций |
| `logs/` | Закрытый постоянный журнал программы в месячных SQLite-файлах |
## Поток данных
Stat2TV XML/JSON разбираются сервисом и сохраняются в нормализованных таблицах
PostgreSQL: турниры, команды, игроки, составы, события и статистика.
Карточки/карьера КХЛ имеют отдельный локальный импорт и синхронизацию.
Рабочее состояние матча и права доступа относятся к матчу; персональный канал,
назначение устройства и mapping определяют получателя данных vMix.
SQL Mapping получает контекст матча/выбора, формирует SetText/SetImage и передаёт
их нужному Agent. Отправка команды и её подтверждение — разные этапы.
Команды действий (например, Toggle/Cut) нельзя повторять без проверки результата.
Восстановление связи должно заново синхронизировать данные, не воспроизводя эфирные действия.
Mapping имеет раздельное ожидаемое и подтверждённое состояние. В ожидании ACK —
не более одной фоновой Mapping-команды на Agent; доставка не блокирует отдельное
чтение heartbeat/ACK. Поколение соединения/назначения отбрасывает устаревшие
подтверждения. Новый WebSocket ждёт актуальную inventory перед восстановлением.
После committed передачи управления обновляется поколение доставки устройств матча.
Шаблон Mapping и опубликованный снимок устройства разделены. Снимок использует
существующие таблицы профилей/полей и хранится как технический профиль, связанный
с устройством. Сохранение шаблона атомарно проверяет ожидаемую версию. Общие SQL
источники остаются общими; параметры контекста разрешаются для конкретного матча.
Эксплуатационный журнал независим от доступности PostgreSQL. Он получает
структурированные события приложения, стандартный Python logging, Uvicorn,
HTTP-аудит и браузерные замеры. Неблокирующая очередь ограничена, запись пакетная;
чтение использует короткие подключения и курсорную пагинацию. Секреты маскируются
до очереди записи. Запись startup/shutdown закрывается штатно и через atexit.
Stat2TV использует общий ограниченный HTTP-пул, а не новое соединение на каждый
запрос. Авторизация и timeout передаются отдельно для каждого запроса;
при завершении сервера HTTP-клиенты закрываются после фоновых задач.
Состояние WebSocket/Agent и часть кэшей находятся в памяти одного процесса.
Поэтому запуск нескольких workers без общего хранилища назначения/очередей
не является способом масштабирования этой версии.
## Пользовательские данные и артефакты
UI хранится атомарно в `settings/local/` либо внешнем `HOCKEY_UI_DATA_DIR`.
Одинаковые сохранения не создают копий. Миграция прежней истории backup выполняется
однократно; исходные root-настройки сохраняются как bootstrap.
`hockey_data/snapshots/` — диагностические XML, а не база рабочего состояния.
Новые имена включают полный SHA-256 содержимого и тип ресурса. Повторные данные
используют прежний путь без перезаписи. История синхронизаций в БД может ссылаться
на эти файлы, поэтому возрастная очистка XML запрещена без сверки ссылок БД.
Автоматический retention относится только к самостоятельным JSON-отчётам discovery.
Флаги и их LICENSE, шаблоны vMix JSON, исходники Go/Agent.exe, SQL-примеры и
проверки входят в проект по назначению. Совпадение имён или содержимого файлов
default и локальной конфигурации не делает их взаимозаменяемыми.