Введение
Telegram-боты — мощный инструмент для автоматизации рабочих процессов. Однако обработка тяжёлых задач непосредственно в обработчиках бота блокирует event loop и приводит к задержкам в ответах. Решение — разделение на асинхронный бот (aiogram) и фоновые воркеры (RQ + Valkey).
Архитектура системы
Полный цикл обработки запроса выглядит так: пользователь отправляет сообщение → бот получает его через aiogram → бот ставит задачу в очередь RQ через Valkey → RQ-воркер обрабатывает задачу → воркер отправляет результат обратно через Telegram API с привязкой к исходному сообщению.
Бот: приём и постановка в очередь
from aiogram import Bot, Dispatcher, types
from redis import Redis
from rq import Queue
bot = Bot(token=BOT_TOKEN)
dp = Dispatcher()
redis_conn = Redis(host=‘localhost’, port=6379)
task_queue = Queue(‘telegram’, connection=redis_conn)
@dp.message()
async def handle_message(message: types.Message):
# Ставим задачу в очередь, не блокируя бот
task_queue.enqueue(
‘workers.send_text_task’,
chat_id=message.chat.id,
text=message.text,
reply_to=message.message_id
)
await message.reply(“⏳ Обрабатываю запрос…”)
Воркер: обработка и ответ
# workers.py
import asyncio
from aiogram import Bot
def send_text_task(chat_id, text, reply_to):
# Обрабатываем задачу (может быть долгой операцией)
result = process_heavy_task(text)
# Отправляем результат через бот
_run_async_task(
_reply_message(chat_id, result, reply_to)
)
async def _reply_message(chat_id, text, reply_to):
bot = Bot(token=BOT_TOKEN)
await bot.send_message(
chat_id=chat_id,
text=text,
reply_to_message_id=reply_to
)
await bot.session.close()
def _run_async_task(coro):
loop = asyncio.new_event_loop()
try:
loop.run_until_complete(coro)
finally:
loop.close()
ValkeyPersistence для хранения состояния
Для отслеживания статуса задач мы используем Valkey (совместимый с Redis). FinishedJobRegistry позволяет боту периодически проверять завершённые задачи и уведомлять пользователей о результатах.
reply_to_message_id для тредов
Важная деталь — сохранение message_id исходного сообщения и передача его в reply_to_message_id при ответе. Это создаёт естественный тред в чате и помогает пользователю связать ответ с запросом, особенно когда несколько запросов обрабатываются параллельно.
Контейнеризация
Бот и воркеры работают в отдельных контейнерах внутри одного Podman-пода. Valkey также запущен в поде, обеспечивая коммуникацию через localhost.
Заключение
Разделение Telegram-бота на фронтенд (aiogram) и бэкенд (RQ-воркеры) обеспечивает отзывчивость бота и масштабируемость обработки. Valkey служит как брокером сообщений, так и хранилищем состояния.