RFB — обновление для 11 независимых серверов Версия: 2.1.1 Дата: 11.10.2026 Каждая машина сама обслуживает домашний матч своей команды (--team). Центральный сборщик не требуется. Существующие 25 маршрутов и структуры успешных ответов для vMix сохранены. Добавлены отдельные маршруты /api_health, /logs, /logs/data и POST /logs/telegram-test. ИСПРАВЛЕНИЕ ПРОПАДАНИЯ ДАННЫХ В ONLINE В версии 2.1.0 очередной ответ game заменял собранный live-объект: составы, статистика и события могли исчезать до следующего box-score/PBP. Дополнительно пустой PBP очищал события, а частичная статистика без isStart/points могла приводить к HTTP 500 на /team_stats. Теперь game, последний принятый box-score и PBP собираются в отдельном объекте. После проверки он публикуется одной заменой. Уже опубликованные данные при сборке не меняются. Обновление game сохраняет известные поля при пустых составах, отсутствующих полях и null; live-статистика и события накладываются из последних принятых ответов для ТОГО ЖЕ матча. Частичный box-score дополняет статистику, сохраняя известные флаги и остальные поля. Новые числовые нули и false применяются как обычные исправления. Пустой PBP при live/завершении матча с уже загруженными событиями отклоняется. До первого события пустой список допустим. Непустой PBP заменяет предыдущий: реальные исправления/удаления событий применяются. Числовое время броска 0 больше не вызывает ошибку преобразования. Неполный первый game нового матча оставляет последний готовый JSON до получения полного состава. Статистика предыдущего матча не переносится в новый. Поздние ответы чужого матча/поколения потоков отбрасываются. Последние принятые box-score/PBP сохраняются в локальном снимке вместе с собранным game. Снимки 2.1.0 читаются с восстановлением live-источников из готового game. На /logs добавлены «Публикация JSON» и состояние «Сохранены данные»: видно, когда ответ не принят, почему и насколько стары данные для эфира. HTTP 200 неполного ответа не обновляет их возраст. В /api_health добавлен блок publication. Форматы существующих выходов и периодичность API-запросов сохранены; дополнительных запросов нет. УСТАНОВКА НА СУЩЕСТВУЮЩИЙ СЕРВЕР 1. Уточните рабочую папку: systemctl show rfb-data.service -p WorkingDirectory 2. Загрузите ZIP на машину через VS Code/SFTP. Распакуйте в ОТДЕЛЬНУЮ папку. Для проекта в /root/RFB выполните: unzip rfb_independent_servers_optimized.zip -d /tmp/rfb-update-2.1.1 sudo bash /tmp/rfb-update-2.1.1/update.sh /root/RFB Вместо /root/RFB укажите фактический WorkingDirectory. Для проверки архива без установки: bash /tmp/rfb-update-2.1.1/update.sh /root/RFB --check Установка кратковременно перезапускает сервис: выполняйте её вне эфира. 3. Проверьте результат: systemctl status rfb-data.service --no-pager curl -s http://127.0.0.1:8000/api_health Откройте http://АДРЕС_МАШИНЫ:8000/logs update.sh проверяет контрольные суммы и синтаксис, сохраняет резервную копию файлов рядом с проектом, останавливает сервис, устанавливает код, отмечает точное время установки, добавляет systemd drop-in и запускает сервис. Затем проверяет локальный /api_health и версию. Доступность API RFB и Telegram для этой проверки не требуется. Если установка после остановки не завершилась, скрипт восстанавливает файлы и прежний drop-in; сервис запускается вновь, если был активен до обновления. Новые файлы, которых не было в старой версии, при откате перемещаются в failed-update внутри резервной копии. Старый .env, виртуальное окружение, --team, --league, --lang и ExecStart сервиса сохраняются. Скрипт требует доступа к systemctl и записи в рабочую папку; обычный запуск — через sudo. Новые параметры конфигурации дополняют polling_config.json. Имеющиеся значения сохраняются; прежний стандарт prepare_minutes=70 заменяется на 90. Свои другие интервалы и лимит проверьте после установки. Новые зависимости Python не нужны; используйте рабочее окружение проекта. Запускайте один процесс сборщика на машину, без нескольких uvicorn workers. Архив содержит 9 файлов: get_data.py, rfb_polling.py, rfb_runtime.py, rfb_logs.html, rfb_version.json, polling_config.json, update.sh, deploy.sh, README_RU.txt. .env, requirements.txt, ваши данные и исходные логи в архив не включены. Для этого обновления deploy.sh запускать НЕ требуется: его загрузка Git-ветки может вернуть старый код. Для будущего deploy.sh добавьте новые файлы в используемую ветку/релиз проекта. МОНИТОРИНГ /logs Страница работает в самом FastAPI без отдельного сервера и внешних CDN. Она показывает: - версию сборки, дату сборки, установку, запуск процесса и время работы; - режим: ожидание, подготовка, live, завершение; - API-запросы и входящие HTTP-запросы отдельно, за последние 60 секунд; - лимит машины и оставшуюся паузу после запрета/ограничения/сетевого сбоя; - состояние каждого источника, возраст последних принятых данных, HTTP-код, длительность ответа и время до следующей попытки; - CPU процесса (в процентах одного ядра), RAM процесса и свободную RAM VM; - графики API, входящих запросов и CPU за последние 15 минут; - долю ответов из кэша, HTTP 503/500, состояния Excel/NAS и Telegram; - журнал последних 400 событий с поиском, фильтром и скачиванием. Графики и счётчики начинаются заново при перезапуске процесса. В журнал поднимается ограниченный хвост локального лог-файла, поэтому видны и недавние события прошлого запуска. Скачивание на странице сохраняет события из её текущего буфера, а не весь суточный журнал. Полный журнал: journalctl -u rfb-data.service --since today --no-pager > rfb-day.log Мониторинг НЕ опрашивает RFB: использует уже имеющиеся данные процесса. Обновление страницы — каждые 5 секунд; скрытая вкладка прекращает опрос. Длинные сообщения ограничены, токены/пароли скрываются, текст HTML экранируется. Журнал не превращается в список каждого запроса vMix. 503 на выходе до готовности данных — ожидание прогрева, 500 — ошибка. DNS/сеть, HTTP 429, HTTP 401/403 и ошибки приложения показываются отдельно. Если сам сервис остановлен, открытая страница перестанет обновляться: она покажет отсутствие связи. Полностью остановленный сервис не может отдать новую HTML-страницу; тогда проверяйте systemctl/journalctl. update.sh сохраняет дату установки в .rfb_deployment.json. При ручном копировании без скрипта страница честно показывает время обнаружения нового кода при запуске. Чтобы отметить установку вручную, после копирования: cd /root/RFB .venv/bin/python rfb_runtime.py --mark-deployed /root/RFB systemctl restart rfb-data.service По желанию добавьте в .env защиту только страницы диагностики: RFB_LOGS_USER=rfb RFB_LOGS_PASSWORD=ваш_пароль Затем перезапустите сервис. Браузер запросит логин и пароль. Выходы vMix и существующие маршруты остаются доступны по прежним адресам. TELEGRAM Используются уже существующие параметры .env: TELEGRAM_TOKEN=токен_вашего_бота TELEGRAM_CHAT_ID=идентификатор_чата Отправка вынесена в отдельный поток: очередь ограничена 128 сообщениями, проблема Telegram больше не задерживает сбор API и выдачу данных. INFO, предупреждения и ошибки поступают в очередь; сводка нагрузки [metrics] не отправляется. Одинаковые предупреждения подавляются на 5 минут. Сводка live остаётся примерно раз в 5 минут. При 429 учитывается retry_after; при неверном токене/чате или запрете — пауза 10 минут; при сетевой ошибке паузы растут. До 3 попыток на сообщение; сообщения старше 30 минут и переполнение очереди учитываются как отброшенные. Очередь сообщений не сохраняется после остановки процесса. Нажмите «Проверить доставку» на /logs. «Добавлен в очередь» означает только постановку в очередь: успешная доставка подтверждается счётчиком и временем последней доставки в блоке Telegram. Тест ограничен одним запросом в минуту. При отказе отображается причина без токена. Если токен/чат не заданы, Telegram отключён и остальная система работает. Сеть до api.telegram.org, доступ бота к чату и реальные учётные данные нужно проверить на каждой VM: локальные проверки использовали имитацию. РЕЖИМЫ И НАГРУЗКА API Без домашнего матча сегодня и до T−90 минут — ожидание: календарь примерно раз в 15 минут, сезоны раз в сутки. Статистика старого матча не запрашивается, последние исправные данные доступны из кэша. Это около 4 календарных запросов в час на машину, около 44 на все 11 ожидающих машин, плюс запуск, сезоны и повторы после ошибок. T−90 минут — подготовка: составы, метаданные, общая статистика; live-status раз в 30 секунд, последние 5 минут перед стартом — раз в 10. Если старт уже известен из календаря, переход планируется к T−90 и не задерживается ещё на 15 минут до следующего календарного опроса. Само наступление времени старта не включает частый live без Online/Live. Live: live-status примерно раз в секунду, box-score и play-by-play раз в 5 секунд. Метаданные и таблица — раз в 5 минут. Сезонная и общая статистика — однократно после успеха, с повтором при ошибках. Полные pregame прекращают опрашиваться после получения готовых данных в live. Другие матчи опрашиваются только при недавнем использовании /games_online и собственном активном матче; не чаще раз в 30 секунд на чужой матч. После завершения — финальное обновление, до 3 попыток на одноразовый источник, затем ожидание через 10 минут. Возобновление игры возвращает live. Ночной матч продолжает обновляться после полуночи. Два изолированных HTTP-транспорта обслуживают оперативные источники и тяжёлую статистику, при этом бюджет у них ОДИН на весь процесс. Тяжёлые ответы не блокируют оперативный Session. Для тяжёлой статистики read timeout 15 секунд; повтор 60, 120, 240 секунд и далее до 15 минут. После двух сетевых/DNS-сбоев включается общая пауза по хосту с одной пробной попыткой; паузы растут до 5 минут. Это уменьшает число попыток, но не исправляет DNS, маршрутизацию или недоступность удалённого сервера. 429 — общая пауза минимум 120 секунд с учётом Retry-After; 401/403 — минимум 600 секунд. Ограничение по времени сохраняется в снимке на диск, включая корректное завершение сервиса. Сбой/невалидный JSON/неполные данные не заменяют последнее исправное значение. Поздние ответы старой группы потоков и чужого матча отбрасываются. По умолчанию max_requests_per_minute=90 НА ОДНУ машину. Это настройка пакета, не подтверждённая квота RFB. Если квота общая по ключу/IP, индивидуальные лимиты надо распределить так, чтобы их сумма укладывалась в неё: 11 одновременно активных машин по 90 дают максимум 990/мин. Без точной квоты гарантировать отсутствие блокировок нельзя. Пустые VM до этого максимума не доходят. Периоды — целевые: ответы API, лимит, случайный разнос запуска и повторные попытки увеличивают задержку. Меньший лимит уменьшит нагрузку ценой более редких live-обновлений. ОПТИМИЗАЦИЯ VM И СОВМЕСТИМОСТЬ - Частые выходы кэшируют уже сериализованный ответ по версиям входных данных и параметрам запроса. При новом счёте/событиях/Excel кэш меняется. - /status копирует только нужные поля вместо всей большой статистики. - HTTP access log отключён; остаются ошибки, агрегированные счётчики и сводка нагрузки раз в 5 минут. Файлы INFO/WARNING/ERROR: до 5 × 5 МБ. - Снимок кэша копируется и записывается только при изменении данных. В ожидании нет постоянных одинаковых больших записей на диск. - Excel/NAS читаются раз в 15 минут в ожидании и раз в минуту в активном режиме. Переход к подготовке сразу будит Excel-поток. - Иконки карт бросков кэшируются на диске; после рестарта используются до обращения к NAS. Первая отрисовка даёт загрузке иконок до 15 секунд. При недоступности NAS работают круги; появление иконок обновляет карты. - Карты бросков строятся при изменении бросков/ресурсов; PNG-кэш ограничен. - /commentary использует один цикл опроса, ждёт завершения предыдущего, реже обновляет страницу вне live и не опрашивает из скрытой вкладки. - Автоперезагрузка Uvicorn выключена. systemd ждёт network-online.target и ограничивает циклы неудачного старта, не меняя расписание перезагрузок VM. Рабочий каталог кэша — .rfb_cache. Для него, logs и .rfb_deployment.json сервису нужен доступ на запись. Кэш должен оставаться локальным и отдельным у каждого сервера/команды. ПРОВЕРКИ Сравнивались старые 25 выходов и новый код: JSON-поля, типы, сортировка, HTML/JSON /status, заголовки и PNG. Проверены настоящие HTTP-обработчики FastAPI с подставными ответами внешних сервисов, обновление кэша после счёта и PBP, ожидание/подготовка/полуночный матч, ошибки 429/DNS, тяжёлая статистика, Telegram, логирование, сохранение снимков и метаданные. Проверены JavaScript страницы, экранирование и смена сессии после рестарта, синтаксис Python и shell, установка/откат в изолированных тестовых папках. Для 2.1.1 воспроизведены четыре сценария очистки данных на старом коде. Проверены чтение во время публикации, частичные/пустые/невалидные ответы, сохранение нулей/false, смена матча, рестарт, миграция кэша 2.1.0, обновление настоящего счёта/событий и диагностика отклонённых обновлений. Реальный API RFB, реальные Telegram-реквизиты и загрузка vMix на ваших серверах здесь не запускались. После установки на первой VM проверьте реальный матч и данные vMix; затем поставьте архив на остальные с их --team.