RFB — обновление для 11 независимых серверов Дата: 06.10.2026 Каждый сервер сам выбирает домашний матч своей команды и обращается к API. Режим выбирается автоматически: ожидание, подготовка, live, завершение. Выбор именно домашней команды (--team) сохранён из исходного проекта. Дата матча определяется в часовом поясе Europe/Moscow; её можно настроить. Что делает сервер 1. Домашнего матча сегодня нет: статистика старого матча не запрашивается. Сервер проверяет календарь примерно раз в 15 минут, список сезонов — раз в сутки. Это около 4 запросов календаря в час на машину, около 44 на все 11 ожидающих машин, плюс запуск/проверка сезонов/повторы ошибок. Последние исправные данные остаются доступными в локальном кэше. 2. Матч сегодня, но до старта больше 70 минут: ожидание, без опроса статистики матча. Календарь обновляется с той же редкой частотой. 3. До старта осталось 70 минут или меньше: загружаются составы и данные для существующих выходов; live-status проверяется раз в 30 секунд, за 5 минут до старта — раз в 10 секунд. Подготовка может начаться позже порога на время очередной проверки календаря — примерно 15 минут. Наступление времени старта само по себе не включает частый live-опрос: требуется Online/Live из календаря или live-status. 4. Матч идёт: целевой интервал live-status — 1 секунда, box-score и play-by-play — 5 секунд. Game/составы и таблица обновляются раз в 5 минут. Данные pregame и pregame-full-stats прекращают запрашиваться после получения собственных полных данных этого матча. Сезонная статистика и статистика карьеры загружаются один раз успешно; при временных ошибках их загрузка продолжается с увеличением пауз. 5. Матч завершён: выполняется финальное обновление game, box-score, play-by-play, standings и общей статистики. live-status проверяется раз в 30 секунд ещё 10 минут, затем сервер переходит в ожидание. Финальные одноразовые загрузки имеют до 3 попыток. Если завершение было временным и live-status снова сообщает Online, live возобновляется. Идущий матч продолжает обновляться после полуночи. При перезапуске недавно начавшийся ночной матч определяется по свежему календарю; для этого используется окно 12 часов от начала. Интервалы являются целевыми: время ответа API, небольшая случайная пауза, общий лимит и паузы после ошибок могут увеличить задержку. Цена снижения нагрузки — обновление статистики игроков/событий примерно раз в 5 секунд. Счёт по четвертям и карты бросков зависят от этих источников. Что изменено в коде - get_data.py: единый календарный контроллер заменил несколько независимых наблюдателей. Календарь проверяется постоянно, поэтому для смены даты, команды соперника или нового матча перезапуск процесса не нужен. - rfb_polling.py: новый общий HTTP-клиент, лимит запросов, обработка ошибок, контроллер состояний и сохранение локальных снимков. - polling_config.json: новые интервалы и лимиты. Обычные --team, --league, --lang и настройки .env продолжают использоваться. - /games_online: HTTP-запросы в обработчике убраны. Каждый вызов читает кэш. Когда этот выход используется во время подготовки/live/завершения собственного матча, фоновый поток обновляет другие актуальные матчи не чаще одного раза в 30 секунд на матч. Собственный live-status повторно не запрашивается. Без собственного активного матча используются сведения календаря; ожидание не запускает live-опрос всей лиги. - Все обращения к статистическому API проходят через один Session и один лимит на процесс. Запуски запросов распределены во времени. Дополнительные потребители данных учитываются в том же лимите. - HTTP 429: общая пауза не менее 120 секунд, с учётом Retry-After. HTTP 401/403: общая пауза не менее 600 секунд. Повторные ошибки увеличивают задержку: 5, 10, 20, 40 секунд и далее до 300 секунд; для неготовых данных и запретов задержка может быть больше. - Ошибка HTTP, ошибочный JSON или явно неполный game не заменяют последнее исправное значение. Проблемы видны в /api_health. - Остановленные группы потоков получают отдельные события остановки. Поздние ответы предыдущей группы или другого матча отбрасываются. Box-score/PBP, пришедшие раньше game, сохраняются до его загрузки. - /team_stats больше не меняет исходные totals при чтении данных. /status читает согласованный снимок данных, публикация Excel защищена. - Исправлены ошибки при пустом fullScore, отсутствии следующего матча, отсутствующих судьях/Excel, делении на ноль в сравнении команд и запросе milestones для vMix без выбранной сортировки. - Карты бросков обновляются при исправлении координат и смене матча, даже если количество бросков прежнее. Добавлен параметр версии ссылки, ограничен кэш старых изображений; адрес /image/... и PNG сохранены. - Milestones использует кэш расчётов, который не портится сортировкой. - NAS-ресурсы загружаются в фоне. Обновление Excel в день без своего матча выполняется раз в 15 минут; в день своего матча — раз в минуту. NAS не входит в лимит статистического API. - Автоперезагрузка Uvicorn отключена; запускается один экземпляр app. - deploy.sh переведён в окончания строк LF для выполнения в Linux. Существующие 25 маршрутов и структура успешных ответов сохранены. Для диагностики добавлен отдельный /api_health. До появления первых данных часть существующих выходов возвращает 503 или прежнюю пустую структуру. Кэш восстанавливается из .rfb_cache в рабочем каталоге; каталог должен быть доступен сервису для записи. Повреждённый снимок игнорируется. Файл .env, исходные requirements.txt и настройки vMix в пакет обновления не входят и остаются у установленного проекта. Как установить на существующий сервер Пакет предназначен для обновления установленного проекта. В архиве: get_data.py, rfb_polling.py, polling_config.json, deploy.sh, README_RU.txt. Новые зависимости Python не добавлены: rfb_polling использует стандартную библиотеку. Используйте существующее рабочее виртуальное окружение. Проверьте рабочий каталог: systemctl show rfb-data.service -p WorkingDirectory Обычно это /root/RFB. Сначала сохраните старые файлы. Из этого каталога: backup_dir="/root/RFB-backup-$(date +%Y%m%d-%H%M%S)" mkdir -p "$backup_dir" cp -a get_data.py deploy.sh "$backup_dir/" Распакуйте файлы обновления в рабочий каталог проекта с заменой. Для запуска обязательны сразу все три файла: get_data.py, rfb_polling.py и polling_config.json. Сохраните существующий .env, --team и настройки запуска сервиса. Перезапустите только сборщик: systemctl restart rfb-data.service systemctl status rfb-data.service --no-pager curl -s http://127.0.0.1:8000/api_health Для этого обновления полный deploy.sh запускать не требуется: его обычная процедура загрузки репозитория может вернуть код старой ветки. Чтобы новый код переживал будущие установки через deploy.sh, все три обязательных файла нужно добавить в используемую ветку/релиз проекта. При ожидании в /api_health должен быть mode=waiting, а счётчик запросов расти редко. При игре mode=live; requests_last_minute не превышает limit_per_minute. pause_seconds показывает паузу после ограничения API. На первом сервере проверьте реальный матч: счёт, составы, статистику, четверти, /games_online и загрузку данных в vMix. После этого установите тот же пакет на остальных машинах. Каждой машине оставьте её --team. Запускайте один процесс сборщика на машину: лимит принадлежит процессу, несколько workers/копий на одной машине получат отдельные лимиты. Как выбрать лимит По умолчанию max_requests_per_minute=90 на ОДНУ машину. Базовые live интервалы задают примерно 84 запроса в минуту до добавления метаданных, календаря и других матчей; общий ограничитель всё равно пропускает не более настроенного бюджета. При его достижении данные обновляются медленнее, пока не освободится очередь. Пустые серверы не опрашивают эти live-источники. 90 — настройка этой версии, а не подтверждённый разрешённый лимит RFB. Если провайдер считает общий IP или общий ключ для всех серверов, 11 независимых ограничителей не обеспечивают общий бюджет 90: теоретический суммарный максимум будет 990 запросов в минуту. Для известного общего бюджета Q распределите индивидуальные лимиты так, чтобы их сумма не превышала Q. Даже при этом неизвестные суточные квоты и правила конкретных endpoint требуют уточнения у провайдера. Уменьшение max_requests_per_minute увеличивает задержку live. Без точной квоты гарантировать отсутствие блокировки нельзя. Дополнительные параметры можно записать в polling_config.json: other_games_demand_seconds (90), snapshot_seconds (30), request_connect_timeout (3), request_read_timeout (5), retry_initial_seconds (5), retry_max_seconds (300), rate_limit_pause_seconds (120), forbidden_pause_seconds (600), cache_directory (".rfb_cache"), shotmap_max_images (192). Путь конфигурации: --poll-config или переменная RFB_POLL_CONFIG. Изменение файла конфигурации требует перезапуска сборщика. Проверки этой версии 38 автономных проверок прошли. Сравнены все 25 существующих маршрутов старой и новой версии на одних контрольных данных, включая порядок полей, значения, типы, HTML и PNG-ответ. Проверены бюджет при нескольких параллельных потребителях, Retry-After, 429/403, возрастающие паузы, ожидание без своего матча, подготовка, следующая дата, завершение, ночной матч, старые ответы, сохранение исправного кэша и пустые данные. Также прошли компиляция Python и bash -n для deploy.sh. Проверки использовали подставные ответы API и компоненты FastAPI, requests и NAS; исходный API не вызывался, полноценный сервер с реальными зависимостями здесь не запускался. Сравнение контрольных ответов не заменяет проверку конкретного матча на вашем сервере.