Перейти к содержимому
Максим Касакин
Все работы

Kineiro LLC · Казахстан · 2025

Платформа автоматизации контента на AI

Роль: Архитектор ПО / Тех-лид

20
моделей: текст, фото, видео, аудио
1,200/day
публикаций, идемпотентно - без дублей
8
соцканалов в одном слое
  • Go
  • NestJS
  • RabbitMQ
  • BullMQ
  • Redis
  • MongoDB
  • SQL
  • Kubernetes
  • Docker

Задача

Продукту нужно было генерировать и публиковать маркетинговый контент в масштабе, сразу на множество социальных платформ, используя ту AI-модель, которая лучше (и доступна) для конкретной задачи. «Доступна» - здесь ключевое слово: провайдеры моделей ограничивают по rate-limit, деградируют и падают. Наивная интеграция застопорила бы весь конвейер при первом же сбое одного провайдера.

Что я построил

Я спроектировал и возглавил разработку платформы с нуля. Ядро - ai-workflow, сервис оркестрации, который распределяет задачи генерации между 20 моделями для текста, изображений, видео и аудио с автоматическим переключением на резерв, батчингом запросов и кэшированием промежуточных результатов в Redis. Когда провайдер деградирует, трафик перетекает на здоровый - пользователь этого не замечает.

На стороне доставки - высокопроизводительный сервис публикации на Go, отправляющий около 1 200 публикаций в день в 8 каналов: Telegram, Facebook, VK и другие. Публикация идемпотентна: повторный запуск задачи никогда не создаёт дубль поста.

Движок воркфлоу

Движок воркфлоу я написал с нуля - сначала на Deno (задачи приходили через RabbitMQ), затем переписал на NestJS ради удобства разработки и расширяемости.

Каждая задача генерации - это воркфлоу: шаги объявляются типизированными классами со своими зависимостями, движок собирает из них DAG (топологическая сортировка) и выполняет уровень за уровнем - независимые шаги параллельно, зависимые по порядку.

RabbitMQзадачи на входЛок задачиидемпотентно · TTLСобытияжизн. циклаДВИЖОК ВОРКФЛОУDAG · топосортировкакаждый шаг → роутинг моделейтекст · фото · видео · аудиошагшагшагшагшагпараллельно в уровне · зависимые ждутКэш шаговPostgresсохраняю шагрезюм - пропуск готовых

Результат каждого шага сохраняется, поэтому движок продолжает с последнего успешного шага: если задача упала или пришла повторно, он подгружает уже выполненные шаги и доделывает только оставшееся - без повторного инференса и недоделанного контента. Межпроцессный лок задачи (с TTL) делает запуски идемпотентными, так что повторная доставка из RabbitMQ или ручной перезапуск не запустят одну задачу дважды. Задачи приходят через RabbitMQ по подключаемому транспортному адаптеру (HTTP тоже поддерживается), а по завершении движок публикует события жизненного цикла для остальной платформы.

Отказоустойчивость

Внешние платформы падают постоянно, поэтому архитектура исходит из того, что сбои неизбежны:

  • Событийно-ориентированные внутренности на BullMQ, развязанные с ранее тесно связанными модулями NestJS.
  • RabbitMQ с гарантированной доставкой между сервисами.
  • Dead-letter queues, повторные попытки с экспоненциальной задержкой и graceful degradation - сбой одной платформы не роняет систему.

Данные и наблюдаемость

Я объединил MongoDB (результаты генерации) и SQL (транзакции, аналитика) в единый слой данных на NestJS и выстроил сквозную наблюдаемость: логирование задержек по этапам, метрики качества инференса и алертинг - чтобы проблемы всплывали раньше, чем о них сообщат клиенты.

Единый модуль авторизации каналов вбирает разнородные OAuth-флоу по платформам (Telegram / Facebook / VK) в один поддерживаемый слой подключения.

Команда и направление

Роль выходила далеко за рамки архитектуры. Я вырастил инженерную команду с 2 до 10 разработчиков - нанимал, онбордил и задавал техническое направление по мере роста. Работал напрямую с отделом продаж и с сопровождением партнёров и клиентов, поэтому роадмап платформы оставался привязан к тому, что реально закрывало сделки и держало интеграции живыми, - а не только к тому, что технически интересно.