Привет, Хабр. С вами снова Вадим.

В прошлом посте я рассказывал, как написал AI-бота Аврора, который ищет вакансии вместо меня.

Статья залетела, и к нам пришли первые 100 тестеров. И тут началось веселье.

Представьте: вы нажимаете кнопку "Найти работу", а бот молчит. 10 секунд, 20 секунд. Вы думаете: "Сломалось" и жмете кнопку еще 5 раз.

А на самом деле бот не сломался. Он просто "ушел на кухню готовить".

В этой статье расскажу, как мы переписали архитектуру с "однорукого повара" на "промышленный конвейер", зачем использовали SQL вместо модного Redis и как наша скорость стала нашей проблемой.

Если вы разработчик - найдете тут код про SKIP LOCKED.

Если вы ищете работу - поймете, почему наш бот теперь быстрее, чем пальцы любого рекрутера.

Проблема: Эффект "Одного Официанта"

Первая версия бота работала по простому принципу (синхронно).

Юзер пишет: "Хочу вакансии".

Бот (скрипт) бежит на хедхантер, качает данные, бежит в нейросеть (Gemini), пишет письмо и возвращается к юзеру.

Это занимает ~15 секунд.

Проблема: Пока бот бегал для одного пользователя, остальные 99 стояли в очереди и видели "зависший" экран.

Telegram не любит, когда боты тупят, и просто обрывал соединение.

Нам нужно было разделить бота на две части:

  1. Официант (Интерфейс): Только принимает заказы. "Принял, ожидайте". Это занимает 0.1 секунды.

  2. Кухня (Воркеры): Армия поваров, которые где-то в подсобке жарят ваши резюме и варят сопроводительные письма.

Техническое решение: Очередь на PostgreSQL

Обычно для таких "кухонь" используют сложные инструменты типа Celery или RabbitMQ.

Но мы стартап, у нас нет лишних денег на сервера.

Поэтому мы сделали очередь прямо в базе данных (PostgreSQL).

Для технарей: мы использовали магию SELECT ... FOR UPDATE SKIP LOCKED.

Для не технарей: представьте, что у нас есть доска с заказами.

Подходит повар (Воркер), берет первый листок.

В обычном мире два повара могут схватиться за один листок и порвать его.

Команда SKIP LOCKED работает как магия: повар видит, что листок уже в чужой руке, и мгновенно берет следующий.

Никаких драк, никаких простоев.

Теперь мы можем запустить хоть 50 "поваров" одновременно. Бот стал отвечать мгновенно.

Факап: Мы стали слишком быстрыми

Мы выкатили обновление. Интерфейс "залетал". Очереди исчезли.

Мы радовались ровно 10 минут.

Потом легли наши логи.

Ошибка: 429 Too Many Requests от hh.ru.

Оказалось, что наша армия цифровых поваров начала работать так быстро, что сайт с вакансиями принял нас за хакерскую атаку (DDOS).

Раньше "тормоза" бота были естественным ограничителем. Теперь, когда тормозов не стало, мы вычерпали лимиты запросо�� за минуту.

Пришлось учить роботов быть людьми.

Мы внедрили искусственное замедление (Rate Limiter).

Теперь бот делает паузы. Он "дышит". Он имитирует поведение человека, который пьет кофе между откликами.

Это парадокс разработки: сначала ты тратишь ночи, чтобы ускорить код, а потом пишешь костыли, чтобы его замедлить.

Что это дает пользователю?

  1. Надежность. Ваш запрос на поиск работы не потеряется, даже если сервер перезагрузится. Он записан в "блокнот" на кухне.

  2. Скорость. Вы можете накидать боту 50 задач (например, "откликнись во все банки") и закрыть Телеграм. Он будет шуршать в фоне, вежливо соблюдая паузы, чтобы вас не забанили.

  3. Результат. За вчерашний день наши "вежливые воркеры" обработали 1500 сложных заявок с AI-генерацией писем. Ни один живой рекрутер с такой скоростью не работает.

Мы не используем модные технологии ради моды. Мы используем SQL, потому что это надежно как автомат Калашникова.

Сейчас мы учим бота не просто искать вакансии, а переписывать ваше резюме так, чтобы HR плакали от счастья. Но об этом (и о том, как заставить нейросеть выдавать JSON) - в следующей серии.

Кому интересно следить за тем, как мы строим "Uber для поиска работы" - велкам в канал. Там мы выкладываем и код, и кейсы трудоустройства.

https://t.me/auroracareer

(В комментах готов пояснить за архитектуру и почему RabbitMQ для бота на 10к юзеров - это оверхед).

Комментарии (0)