Long Polling¶
Long Polling (длинный опрос) - простой способ получения обновлений от сервера. Бот отправляет запрос к API и, если новых событий нет, сервер держит соединение открытым некоторое время (timeout), ожидая их появления.
Этот метод подходит для разработки и простых ботов, так как не требует публичного IP-адреса или настройки SSL-сертификатов (в отличие от Webhook).
Предупреждение
Если вы запустите несколько процессов бота с одним токеном, использующих Long Polling, каждый из них будет получать копии одних и тех же обновлений.
Это особенность работы API Max.ru: сервер не распределяет нагрузку между подключенными клиентами Long Polling, а рассылает события всем активным слушателям. В результате ваши боты будут дублировать ответы пользователям.
Примечание
Для масштабирования (запуска нескольких экземпляров бота) или работы под высокой нагрузкой необходимо использовать Webhook. В этом случае сервер Max.ru будет отправлять каждое обновление только один раз на ваш endpoint, и вы сможете распределять нагрузку между воркерами (например, с помощью Nginx или Kubernetes).
Использование¶
Для запуска поллинга используется класс LongPolling.
import os
from maxo import Bot, Dispatcher
from maxo.transport.long_polling import LongPolling
bot = Bot(token=os.environ["TOKEN"])
dispatcher = Dispatcher()
# ... регистрация хендлеров ...
if __name__ == "__main__":
# Запуск поллинга
LongPolling(dispatcher).run(bot)
Если вы уже находитесь в асинхронном контексте, используйте метод start вместо run:
from maxo.transport.long_polling import LongPolling
await LongPolling(dispatcher).start(bot)
Параметры запуска¶
Метод run принимает несколько аргументов для настройки поллинга:
timeout(int, по умолчанию 30) - время в секундах, которое сервер будет держать соединение открытым, ожидая новых событий. Чем больше значение, тем меньше «пустых» запросов делает бот.limit(int, по умолчанию 100) - максимальное количество обновлений, которое сервер вернет за один запрос.drop_pending_updates(bool, по умолчанию False) - еслиTrue, бот при запуске пропустит все обновления, которые накопились, пока он был выключен. Полезно при разработке.types(list[str], опционально) - список типов обновлений, которые вы хотите получать. Если не указано, maxo автоматически определит этот список на основе зарегистрированных обработчиков.
from maxo.transport.long_polling import LongPolling
LongPolling(dispatcher).run(
bot,
timeout=60,
drop_pending_updates=True,
)
Пропуск старых обновлений¶
Иногда при перезапуске бота нужно игнорировать все, что накопилось за время простоя (например, чтобы бот не начал отвечать на сообщения часовой давности).
from maxo.transport.long_polling import LongPolling
LongPolling(dispatcher).run(bot, drop_pending_updates=True)
Автоматическая обработка ошибок¶
Встроенный поллер в maxo устойчив к сбоям сети. Если запрос к API завершится ошибкой (например, проблемы с интернетом или сервером), поллер не упадет, а:
Залогирует ошибку.
Подождет некоторое время (используя стратегию Exponential Backoff).
Повторит запрос.
Это гарантирует, что ваш бот автоматически восстановит работу при возобновлении связи.
Конкурентная обработка¶
Поллер использует asyncio.TaskGroup для обработки обновлений. Это означает, что новые обновления могут обрабатываться параллельно, не блокируя друг друга.