Files
new_lottery_bot/docs/CHAT_SCHEDULER.md
Andrew K. Choi a0e6a385b6
Some checks reported errors
continuous-integration/drone/push Build encountered an error
docs: добавлена документация по планировщику рассылки
- Подробное описание работы планировщика с пакетной отправкой
- Математика расчета скорости отправки (10-13 сообщений/сек)
- Рекомендации по настройке параметров BATCH_SIZE и BATCH_DELAY
- Примеры для разных размеров групп пользователей
- Troubleshooting распространенных проблем
- Объяснение защиты от блокировки Telegram (лимит 30 сообщений/сек)
2025-11-16 14:37:20 +09:00

10 KiB
Raw Blame History

Настройка планировщика рассылки

Проблема

Telegram имеет лимиты на количество отправляемых сообщений:

  • 30 сообщений в секунду для ботов
  • При превышении возникает ошибка Too Many Requests (код 429)
  • Бот может быть временно заблокирован

Решение

Реализован планировщик пакетной рассылки с контролируемой задержкой между пакетами.

Параметры планировщика

# В файле src/handlers/chat_handlers.py

BATCH_SIZE = 20     # Количество сообщений в одном пакете
BATCH_DELAY = 1.0   # Задержка между пакетами в секундах

Как это работает

  1. Получение списка пользователей:

    • Загружаются все зарегистрированные пользователи (is_registered=True)
    • Исключается отправитель сообщения
  2. Разбиение на пакеты:

    • Пользователи разбиваются на группы по BATCH_SIZE (по умолчанию 20)
    • Например, 100 пользователей = 5 пакетов по 20
  3. Параллельная отправка внутри пакета:

    • В каждом пакете сообщения отправляются параллельно через asyncio.gather()
    • Это ускоряет доставку без превышения лимитов
  4. Задержка между пакетами:

    • После отправки пакета выжидается BATCH_DELAY секунд
    • Это предотвращает превышение лимита 30 сообщений/сек
  5. Обработка ошибок:

    • Ошибки отправки отлавливаются для каждого пользователя
    • Статистика успешных/неуспешных доставок ведется отдельно

Математика

Скорость отправки:

  • Пакет из 20 сообщений отправляется параллельно ≈ за 0.5-1 секунду
  • Задержка между пакетами: 1 секунда
  • Итого: ~20 сообщений за 1.5-2 секунды = 10-13 сообщений/сек
  • Это в 2-3 раза меньше лимита Telegram (30/сек)

Пример для 100 пользователей:

  • 5 пакетов по 20 сообщений
  • Время отправки: 5 × (1 сек отправка + 1 сек задержка) = 10 секунд
  • Средняя скорость: 10 сообщений/сек

Пример для 1000 пользователей:

  • 50 пакетов по 20 сообщений
  • Время отправки: 50 × 2 сек = 100 секунд (1.5 минуты)
  • Средняя скорость: 10 сообщений/сек

Настройка параметров

Увеличение скорости

Если нужно быстрее рассылать и у вас стабильное соединение:

BATCH_SIZE = 25     # Больше сообщений в пакете
BATCH_DELAY = 0.8   # Меньше задержка

⚠️ Риск: При > 30 сообщений/сек может быть блокировка

Уменьшение нагрузки

Если возникают ошибки 429 или нестабильное соединение:

BATCH_SIZE = 15     # Меньше сообщений в пакете
BATCH_DELAY = 1.5   # Больше задержка

Безопаснее: Меньше шанс блокировки

Для VIP ботов (верифицированных)

Telegram может повысить лимиты для верифицированных ботов:

BATCH_SIZE = 30     # Можно больше
BATCH_DELAY = 0.5   # Можно быстрее

Пример работы

Код функции

async def broadcast_message_with_scheduler(message: Message, exclude_user_id: Optional[int] = None):
    """Разослать сообщение всем пользователям с планировщиком"""
    async with async_session_maker() as session:
        users = await get_all_active_users(session)
    
    if exclude_user_id:
        users = [u for u in users if u.telegram_id != exclude_user_id]
    
    forwarded_ids = {}
    success_count = 0
    fail_count = 0
    
    # Разбиваем на пакеты
    for i in range(0, len(users), BATCH_SIZE):
        batch = users[i:i + BATCH_SIZE]
        
        # Отправляем пакет параллельно
        tasks = [_send_message_to_user(message, u.telegram_id) for u in batch]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # Подсчитываем статистику
        for user, result in zip(batch, results):
            if isinstance(result, Exception):
                fail_count += 1
            elif result is not None:
                forwarded_ids[str(user.telegram_id)] = result
                success_count += 1
            else:
                fail_count += 1
        
        # Задержка между пакетами
        if i + BATCH_SIZE < len(users):
            await asyncio.sleep(BATCH_DELAY)
    
    return forwarded_ids, success_count, fail_count

Статистика для пользователя

После рассылки пользователь видит:

✅ Сообщение разослано!
📤 Доставлено: 95
❌ Не доставлено: 5

Причины неуспешной доставки:

  • Пользователь заблокировал бота
  • Пользователь удалил аккаунт
  • Временные сетевые проблемы
  • Ограничения Telegram на стороне получателя

История сообщений

Все ID отправленных сообщений сохраняются в БД:

-- Таблица chat_messages
forwarded_message_ids JSONB

-- Пример данных:
{
  "123456789": 12345,  -- telegram_id: message_id
  "987654321": 12346,
  "555555555": 12347
}

Это позволяет:

  • Удалять сообщения у всех пользователей через /delete_msg
  • Отслеживать кому было доставлено сообщение
  • Собирать статистику рассылок

Рекомендации

Для маленьких групп (< 50 пользователей)

Можно использовать параметры по умолчанию:

BATCH_SIZE = 20
BATCH_DELAY = 1.0

Для средних групп (50-200 пользователей)

Рекомендуется:

BATCH_SIZE = 20
BATCH_DELAY = 1.0

Время рассылки: ~20-40 секунд

Для больших групп (200-1000 пользователей)

Рекомендуется:

BATCH_SIZE = 25
BATCH_DELAY = 1.0

Время рассылки: ~1.5-3 минуты

Для очень больших групп (> 1000 пользователей)

Рассмотрите:

  • Увеличение BATCH_SIZE до 30
  • Использование очередей (RabbitMQ, Celery)
  • Распределение нагрузки на несколько ботов

Мониторинг

Для отслеживания работы планировщика смотрите логи:

tail -f logs/bot.log | grep "Failed to send"

Каждая неуспешная отправка логируется:

Failed to send message to 123456789: Forbidden: bot was blocked by the user
Failed to send message to 987654321: Bad Request: chat not found

Тестирование

Для тестирования планировщика:

  1. Создайте несколько тестовых аккаунтов
  2. Отправьте сообщение через бота
  3. Проверьте время доставки и статистику
  4. Настройте параметры под свою нагрузку

Troubleshooting

Ошибка "Too Many Requests"

Симптомы: Бот периодически выдает ошибку 429

Решение:

BATCH_SIZE = 15      # Уменьшить размер пакета
BATCH_DELAY = 1.5    # Увеличить задержку

Медленная рассылка

Симптомы: Рассылка занимает слишком много времени

Решение:

BATCH_SIZE = 25      # Увеличить размер пакета
BATCH_DELAY = 0.8    # Уменьшить задержку

⚠️ Следите за ошибками 429!

Большое количество неуспешных доставок

Причины:

  • Пользователи массово блокируют бота
  • Проблемы с сетью/сервером
  • Некорректные telegram_id в базе

Решение:

  • Регулярно очищайте неактивных пользователей
  • Мониторьте состояние сервера
  • Валидируйте данные при регистрации

Итого

Защита от блокировки: Лимит 30 сообщений/сек не превышается
Гибкость: Легко настроить под свою нагрузку
Статистика: Точный подсчет успешных/неуспешных доставок
История: Все ID сохраняются для модерации
Параллелизм: Быстрая отправка внутри пакета

Рекомендуемые параметры:

BATCH_SIZE = 20
BATCH_DELAY = 1.0

Это обеспечивает баланс между скоростью и безопасностью.