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 для обработки обновлений. Это означает, что новые обновления могут обрабатываться параллельно, не блокируя друг друга.