Files
hockey_new/docs/ARCHITECTURE.md

14 KiB
Raw Blame History

Архитектура

Модули

Каталог Назначение
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-файлах

Поток данных

BUILD200 сохраняет владельца плашки удаления вместе с её циклом показа, чтобы переход 4on4 → PP не переносил текущий титр на другую сторону. Подтверждение нужных команд vMix предшествует фиксации завершения штрафа в панели; ошибка доставки сохраняет карточку для проверки, неизвестный исход не воспроизводится.

BUILD199 хранит разрешение связанных плашек в флаге матча scoreboard_auxiliaries_enabled. Checkbox и F2 используют один контролируемый запрос; на отправке заново проверяются матч, роль, версия намерения и конкретные Input/Overlay. Gate отделён от часов и подготовки данных. Снятие не отменяет native Countdown, а повторное включение сохраняет исходный срок задержки счёта.

Обработка гола выполняется у действующего оператора по новой команде +1 или одиночному приросту уже наблюдаемого SQL/API-счёта. Первый снимок и изменение источника задают базу. История хранит идентификатор обработанного перехода и снимок изменения штрафа для защиты от повторов и осторожной отмены гола. Для подтверждаемого изменения штрафа native-команды формируются перед самой отправкой по текущему состоянию конкретного Input/SelectedName, чтобы поздний Start не возобновил уже приостановленные часы и не затронул соседнее поле.

Stat2TV XML/JSON разбираются сервисом и сохраняются в нормализованных таблицах PostgreSQL: турниры, команды, игроки, составы, события и статистика. Карточки/карьера КХЛ имеют отдельный локальный импорт и синхронизацию. Рабочее состояние матча и права доступа относятся к матчу; персональный канал, назначение устройства и mapping определяют получателя данных vMix.

SQL Mapping получает контекст матча/выбора, формирует SetText/SetImage и передаёт их нужному Agent. Отправка команды и её подтверждение — разные этапы. Команды действий (например, Toggle/Cut) нельзя повторять без проверки результата. Восстановление связи должно заново синхронизировать данные, не воспроизводя эфирные действия.

Mapping имеет раздельное ожидаемое и подтверждённое состояние. На Agent ожидается ACK не более одного пакета Mapping. Agent с явной capability mapping_title_batch_v1 получает команды, сгруппированные по Input, до 500 команд и 48 КиБ; прежние версии получают до шести независимых установок. Новый Agent сохраняет порядок записей одной цели, выполняет независимые цели ограниченным пулом и выделяет отдельный обработчик для интерактивных команд. WebSocket reader продолжает читать назначения, heartbeat и управление во время массовой отправки. Очереди и время обработки ограничены.

Ошибки отдельных полей не прерывают первый проход по остальным; безопасные повторы выполняются после него. Частичный результат отличается от полной обработки. SQL-каталог ограничен источниками действующих записей и правил, включая зависимости настроенного счёта. Поколение соединения/назначения отбрасывает устаревшие подтверждения. Новый WebSocket ждёт актуальную inventory перед восстановлением. После committed передачи управления обновляется поколение доставки устройств матча.

Шаблон Mapping и опубликованный снимок устройства разделены. Снимок использует существующие таблицы профилей/полей и хранится как технический профиль, связанный с устройством. Сериализация устройства внутри транзакции передаёт её же session в публикацию Mapping, без вложенного подключения с конкурирующей блокировкой. Сохранение шаблона атомарно проверяет ожидаемую версию. Общие SQL источники остаются общими; параметры контекста разрешаются для конкретного матча.

Эксплуатационный журнал независим от доступности PostgreSQL. Он получает структурированные события приложения, стандартный Python logging, Uvicorn, HTTP-аудит и браузерные замеры. Неблокирующая очередь ограничена, запись пакетная; чтение использует короткие подключения и курсорную пагинацию. Секреты маскируются до очереди записи. Запись startup/shutdown закрывается штатно и через atexit.

Сводка готовности к эфиру читает только назначение и опубликованный Mapping выбранного устройства, доступного текущему аккаунту. Она сопоставляет цели с inventory текущего WebSocket и использует подтверждения обработки Mapping текущего поколения. Просмотр не исполняет SQL источников, не создаёт публикации и не отправляет команды Agent. Эти подтверждения живут в памяти процесса; после смены контекста или разрыва связи прежний успех не доказывает готовность.

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 и локальной конфигурации не делает их взаимозаменяемыми.

Ответы браузерных запросов матча привязаны к поколению выбора и сессии. Загрузка общих данных провайдера сохраняет рабочий контекст выбранного матча. Эффективный SQL-счёт берётся из текущего Game либо проверенного результата настроенного ключа для каждой стороны; ручные значения хранятся отдельно.

В BUILD198 право просмотра матча, DATA/Mapping своему Agent и право управления разделены. Выбор роли завершается перед включением блокирующего loader; устаревший выбор и объединённые запросы проверяют поколение запроса. Операторские маршруты по-прежнему проверяют владельца управления. Заполнение по опубликованному Mapping не предоставляет права выполнять произвольные команды.

Показ использует барьер подтверждённых данных конкретного Input. Явные setters подтверждаются до IN/Preview; неполный Mapping не подтверждает готовность титра, требующего данных. Ошибка подготовки блокирует последующий показ этой цели, сохраняя обработку независимых титров. Все автоматические пути общей плашки используют одну задержку от показа основного счёта. Снятие фиксирует связанные цели, отменяет ожидающий IN и проверяет Input/владельца перед каждым OUT.

Agent 1.5.6 согласует vmix_priority_v1: bounded-очереди срочного управления, обычных команд и Mapping. Общая HTTP-ёмкость равна 6, обычное управление и Mapping совместно ограничены 5. Цепочки одной физической цели и Overlay сохраняют причинный порядок между очередями. Новое явное обновление поля снимает право устаревшего Mapping записывать это поле; пропуск не считается успешным ACK. Корреляция trace_id связывает отдельные монотонные замеры браузера, сервера и Agent. Часы разных компьютеров не вычитаются друг из друга.

В BUILD197 браузер связывает загрузку матча с поколением, аккаунтом, сессией, языком и выбранным устройством. Mapping ждёт полных составов обеих команд. Изменение упорядоченных данных игроков запускает полный apply выбранного Agent со свежим разрешением SQL; одинаковые снимки объединяются. Признаки счёта, времени, статистики и timestamps не входят в отпечаток состава. Ответ старой отправки не закрывает окно нового матча. Полный apply сохраняет существующую защиту native Countdown: поля таймеров исключаются до разрешения зависимостей.