feature/chat-system #1
289
docs/CHAT_SCHEDULER.md
Normal file
289
docs/CHAT_SCHEDULER.md
Normal file
@@ -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
|
||||
```
|
||||
|
||||
Это обеспечивает баланс между скоростью и безопасностью.
|
||||
Reference in New Issue
Block a user