From a0e6a385b6c822424f629a819fc366d399252e5e Mon Sep 17 00:00:00 2001 From: "Andrew K. Choi" Date: Sun, 16 Nov 2025 14:37:20 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=BF=D0=BB?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D1=89=D0=B8=D0=BA=D1=83=20?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Подробное описание работы планировщика с пакетной отправкой - Математика расчета скорости отправки (10-13 сообщений/сек) - Рекомендации по настройке параметров BATCH_SIZE и BATCH_DELAY - Примеры для разных размеров групп пользователей - Troubleshooting распространенных проблем - Объяснение защиты от блокировки Telegram (лимит 30 сообщений/сек) --- docs/CHAT_SCHEDULER.md | 289 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 docs/CHAT_SCHEDULER.md diff --git a/docs/CHAT_SCHEDULER.md b/docs/CHAT_SCHEDULER.md new file mode 100644 index 0000000..e541282 --- /dev/null +++ b/docs/CHAT_SCHEDULER.md @@ -0,0 +1,289 @@ +# Настройка планировщика рассылки + +## Проблема + +Telegram имеет лимиты на количество отправляемых сообщений: +- **30 сообщений в секунду** для ботов +- При превышении возникает ошибка `Too Many Requests` (код 429) +- Бот может быть временно заблокирован + +## Решение + +Реализован **планировщик пакетной рассылки** с контролируемой задержкой между пакетами. + +### Параметры планировщика + +```python +# В файле 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 сообщений/сек + +### Настройка параметров + +#### Увеличение скорости + +Если нужно быстрее рассылать и у вас стабильное соединение: + +```python +BATCH_SIZE = 25 # Больше сообщений в пакете +BATCH_DELAY = 0.8 # Меньше задержка +``` + +⚠️ **Риск:** При > 30 сообщений/сек может быть блокировка + +#### Уменьшение нагрузки + +Если возникают ошибки 429 или нестабильное соединение: + +```python +BATCH_SIZE = 15 # Меньше сообщений в пакете +BATCH_DELAY = 1.5 # Больше задержка +``` + +✅ **Безопаснее:** Меньше шанс блокировки + +#### Для VIP ботов (верифицированных) + +Telegram может повысить лимиты для верифицированных ботов: + +```python +BATCH_SIZE = 30 # Можно больше +BATCH_DELAY = 0.5 # Можно быстрее +``` + +## Пример работы + +### Код функции + +```python +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 отправленных сообщений сохраняются в БД: + +```sql +-- Таблица chat_messages +forwarded_message_ids JSONB + +-- Пример данных: +{ + "123456789": 12345, -- telegram_id: message_id + "987654321": 12346, + "555555555": 12347 +} +``` + +Это позволяет: +- Удалять сообщения у всех пользователей через `/delete_msg` +- Отслеживать кому было доставлено сообщение +- Собирать статистику рассылок + +## Рекомендации + +### Для маленьких групп (< 50 пользователей) + +Можно использовать параметры по умолчанию: + +```python +BATCH_SIZE = 20 +BATCH_DELAY = 1.0 +``` + +### Для средних групп (50-200 пользователей) + +Рекомендуется: + +```python +BATCH_SIZE = 20 +BATCH_DELAY = 1.0 +``` + +Время рассылки: ~20-40 секунд + +### Для больших групп (200-1000 пользователей) + +Рекомендуется: + +```python +BATCH_SIZE = 25 +BATCH_DELAY = 1.0 +``` + +Время рассылки: ~1.5-3 минуты + +### Для очень больших групп (> 1000 пользователей) + +Рассмотрите: +- Увеличение `BATCH_SIZE` до 30 +- Использование очередей (RabbitMQ, Celery) +- Распределение нагрузки на несколько ботов + +## Мониторинг + +Для отслеживания работы планировщика смотрите логи: + +```bash +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 + +**Решение:** +```python +BATCH_SIZE = 15 # Уменьшить размер пакета +BATCH_DELAY = 1.5 # Увеличить задержку +``` + +### Медленная рассылка + +**Симптомы:** Рассылка занимает слишком много времени + +**Решение:** +```python +BATCH_SIZE = 25 # Увеличить размер пакета +BATCH_DELAY = 0.8 # Уменьшить задержку +``` + +⚠️ Следите за ошибками 429! + +### Большое количество неуспешных доставок + +**Причины:** +- Пользователи массово блокируют бота +- Проблемы с сетью/сервером +- Некорректные telegram_id в базе + +**Решение:** +- Регулярно очищайте неактивных пользователей +- Мониторьте состояние сервера +- Валидируйте данные при регистрации + +## Итого + +✅ **Защита от блокировки**: Лимит 30 сообщений/сек не превышается +✅ **Гибкость**: Легко настроить под свою нагрузку +✅ **Статистика**: Точный подсчет успешных/неуспешных доставок +✅ **История**: Все ID сохраняются для модерации +✅ **Параллелизм**: Быстрая отправка внутри пакета + +**Рекомендуемые параметры:** +```python +BATCH_SIZE = 20 +BATCH_DELAY = 1.0 +``` + +Это обеспечивает баланс между скоростью и безопасностью.