Очередь сообщений для бота — это буфер между площадкой и вашей логикой ответа. Площадка присылает событие о новом сообщении, вы кладёте его в очередь и отвечаете «принято» за доли секунды, а обрабатываете отдельно и в своём темпе.
Без этого буфера бот работает ровно до первого всплеска или первой ошибки. Дальше начинается то, что снаружи выглядит как «бот сломался», а внутри — как потерянные события, дубли ответов и висящие запросы.
Что происходит без очереди
Наивная схема выглядит так: пришёл вебхук — сходили в языковую модель — отправили ответ — вернули код 200. В спокойный день это работает.
Проблемы начинаются в четырёх местах:
- Модель отвечает секунды. Пока запрос висит, вебхук ждёт. Площадка не ждёт бесконечно и считает доставку неуспешной.
- Неуспешную доставку присылают повторно. Вы обрабатываете одно и то же сообщение дважды и отправляете покупателю два ответа.
- Всплеск. После публикации объявления приходит пятнадцать сообщений за минуту. Пятнадцать параллельных запросов к модели — это либо превышение лимита, либо счёт, либо и то и другое.
- Любая ошибка теряет сообщение навсегда. Упал процесс, кончился токен, отвалилась сеть — событие не вернётся, покупатель останется без ответа.
Очередь снимает все четыре разом: приём и обработка перестают быть одним действием.
Минимальная схема, которой достаточно
Не нужен брокер. Для потока обычного продавца хватает таблицы в базе.
таблица inbox: event_id уникальный идентификатор события площадки chat_id диалог message_id сообщение payload тело status new | processing | done | failed attempts счётчик попыток next_try_at когда можно повторить created_at
Приёмник делает одно: вставляет строку и отвечает 200. Вставка с уникальным индексом по идентификатору события сразу решает проблему дублей — повтор просто не запишется.
Обработчик в цикле берёт одну строку со статусом new, помечает её processing, делает работу и ставит done. При ошибке — увеличивает счётчик попыток и отодвигает next_try_at.
Здесь важна деталь: строку надо брать так, чтобы её не взял второй обработчик одновременно. В большинстве баз это делается блокировкой строки при выборке. Если обработчик один, задача снимается сама собой, но тогда он становится узким местом при всплеске.
Идемпотентность: главное свойство
Любое событие может прийти дважды. Это не сбой площадки, а нормальное свойство доставки: отправитель не знает, потерялся ли ответ, и повторяет.
Значит, обработка должна давать один и тот же результат при повторе. Практически это два правила:
- Уникальный ключ на идентификаторе сообщения при записи в очередь.
- Проверка перед отправкой: не отвечали ли мы уже на это сообщение.
Второе нужно потому, что дубль может возникнуть и внутри вашей системы — например, обработчик упал после отправки ответа, но до записи статуса. Дешёвая защита: хранить идентификатор последнего сообщения, на которое бот ответил в этом диалоге.
Склейка сообщений и пауза перед ответом
Покупатели пишут не абзацами, а очередями: «Здравствуйте», «Ещё актуально?», «А доставка есть?» — три события за десять секунд. Бот без склейки ответит три раза, причём первый ответ будет на «Здравствуйте».
Правильное поведение: после появления сообщения подождать несколько секунд, забрать всё, что пришло в этом диалоге за это время, и ответить один раз на всё сразу.
Та же пауза решает вторую задачу — про неё редко пишут, но она важна. Отвечать мгновенно не нужно. Ответ через полсекунды после сообщения читается как автомат, и часть покупателей сразу теряет интерес к разговору. Задержка в несколько десятков секунд не проигрывает гонку за внимание, но выглядит как живой человек, который дописал предыдущий диалог. Насколько скорость вообще решает, разобрано отдельно — как отвечать на Авито быстро.
Практический ориентир: пауза от двадцати секунд до минуты, случайная в пределах диапазона, и обязательно короче, чем у конкурентов. Цифры для примера, подбирайте по своей нише.
Если строить это самому не хочется, вся описанная механика уже работает внутри: бот «Папы БУ» держит очередь, склейку сообщений и повторы на своей стороне, а от вас нужен только список фактов о товаре и о том, чего вы не делаете.
Повторы, тайм-ауты и мёртвые письма
Три настройки, без которых очередь превращается в бесконечный цикл.
Ограничение попыток. Три-пять, дальше статус failed и уведомление вам. Сообщение, которое не удалось обработать двадцать раз, не обработается и в двадцать первый.
Растущая пауза между попытками. Секунда, десять, минута, пять минут. Если у площадки временные проблемы, вы не добьёте её своими повторами.
Отдельная полка для неудач. Разбирать failed руками раз в день — нормальная практика. Хуже, когда такие события исчезают бесследно и вы узнаёте о них от покупателя.
Отдельно про токены доступа: срок их жизни ограничен, и обновление лучше делать заранее, а не по факту ошибки. Как устроен доступ — в разборе, как подключить API Авито.
Что мониторить
Очередь хороша тем, что делает состояние бота измеримым. Смотреть стоит на четыре числа: длину очереди new, время от поступления до ответа, долю failed, число повторных попыток за сутки.
Растущая длина очереди означает, что обработчик не справляется. Растущее время ответа при короткой очереди — что тормозит модель или площадка. Скачок failed — что сломался доступ.
Когда очередь не нужна
Честно: не всегда.
Пять диалогов в неделю. Прямая обработка вебхука проще, и потеря одного сообщения решается ручным ответом.
Бот только уведомляет вас. Если внешняя система не вызывается и ответ не генерируется, обработка занимает миллисекунды и буфер избыточен.
Вы не готовы поддерживать инфраструктуру. Очередь — это ещё один процесс, который надо перезапускать, мониторить и чинить ночью. Ночные диалоги при этом никуда не деваются: ответы ночью на Авито — отдельная тема, и она добавляет требований к надёжности.
Коротко
Очередь сообщений для бота нужна затем, чтобы приём события и ответ на него перестали быть одним действием. Минимум — таблица со статусом и счётчиком попыток, уникальный ключ против дублей, склейка сообщений одного диалога, пауза перед ответом, ограниченные повторы с растущим интервалом и отдельная полка для неудач.
Всё это — примерно неделя работы разработчика плюс постоянная поддержка. Если считать эту неделю дорогой, посмотрите, как то же самое устроено у нас: три дня бесплатно, подключение занимает вечер.
Если решение под свой бизнес нужно, а разбираться самому некогда — напишите мне в Telegram: @artem_sergeevic. Я делаю такие сервисы на заказ: обсудим задачу и честно разберём, что в ней действительно нужно, а что можно не делать вовсе.