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 завершится ошибкой (например, проблемы с интернетом или сервером), поллер не упадет, а:

  1. Залогирует ошибку.

  2. Подождет некоторое время (используя стратегию Exponential Backoff).

  3. Повторит запрос.

Это гарантирует, что ваш бот автоматически восстановит работу при возобновлении связи.

Конкурентная обработка#

Поллер использует asyncio.TaskGroup для обработки обновлений. Это означает, что новые обновления могут обрабатываться параллельно, не блокируя друг друга.