177 lines
16 KiB
Plaintext
177 lines
16 KiB
Plaintext
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 не вызывался, полноценный сервер с
|
||
реальными зависимостями здесь не запускался. Сравнение контрольных
|
||
ответов не заменяет проверку конкретного матча на вашем сервере.
|