Перейти к содержимому

Обмен сообщениями: RabbitMQ + WebSocket

Реалтайм-часть системы (диалог с AI-агентом) работает не по модели «запрос-ответ», а через три транспорта в одном сервисе ai-agent-service: HTTP (история/состояние), WebSocket (Socket.IO, клиентский канал) и RabbitMQ (обмен с внешним AI-агентом Walrider).

Полные детали — ai-agent-service и walrider. Здесь — операционная топология.

flowchart LR
Client[Клиент<br/>Socket.IO]
subgraph AI[ai-agent-service]
GW[WS Gateway<br/>ns /agent-chat]
SVC[AgentChat Service]
PROD[Rabbit producer]
CONS[Rabbit consumer]
end
subgraph MQ[RabbitMQ]
RX[[requestExchange]]
RQ[(requestQueue<br/>TTL 600с, DLX ai.dlx)]
SX[[responsesExchange]]
SQ[(responsesQueue)]
end
WAL[Внешний AI-агент<br/>Walrider]
RD[(Redis<br/>ws:project:id)]
PG[(PostgreSQL<br/>WalriderThread/Message/State)]
Client -- sendMessage --> GW --> SVC
SVC --> PROD --> RX --> RQ --> WAL
WAL --> SX --> SQ --> CONS --> SVC
SVC -- message --> GW -- message --> Client
SVC <--> RD
SVC <--> PG
Обмен → ОчередьПродюсерКонсьюмерОсобенности
requestExchangerequestQueueai-agent-serviceвнешний WalriderTTL 600с, dead-letter exchange ai.dlx
responsesExchangeresponsesQueueвнешний Walriderai-agent-servicerouting key пустой ''

Контракты сообщений (rabbit-messages.interface.ts):

  • Запрос: RabbitRequestMessage { messageId, threadId, content }
  • Ответ: RabbitResponseMessage { messageId, threadId, response, phase, isComplete, plan }

Подключение к RabbitMQ — вручную через amqplib (util rabbit-client), конфиг — configs/shared/rabbit (переменные RABBITMQ_HOST/PORT/USERNAME/PASSWORD, RABBITMQ_REQUEST_*, RABBITMQ_RESPONSES_*, RABBITMQ_PREFETCH).

  • Namespace: /agent-chat
  • Комнаты: project:{projectId} (один тред = один проект)
  • Авторизация: JWT + projectId в query handshake
СобытиеНаправлениеPayload
connection / disconnectжизненный цикл сокета
sendMessageclient → server{ content }
messageSentserver → client{ messageId } (ack)
messageserver → client{ messageId, response, phase, isComplete, plan }

Активный сокет проекта хранится в Redis по ключу ws:project:{projectId} — чтобы доставить асинхронный ответ из очереди нужному соединению.

  • project-api при создании проекта заводит WalriderThread (1:1 с проектом) в той же транзакции — это «регистрация» диалога.
  • ai-agent-service — весь рантайм: продюсер запросов, консьюмер ответов, WS-шлюз и REST-эндпоинты истории/состояния.
  • Внешний Walrider — консьюмер запросов и продюсер ответов; собственно «мозг» AI.

Оба сервиса (project-api и ai-agent-service) держат свою копию WalriderThreadRepository поверх общей Prisma-схемы. Подробнее о сущностях thread/message/state и поле planwalrider.

  • Для ai-agent-service обязателен доступ к RabbitMQ и Redis (кроме PostgreSQL). Без Redis не доставляются асинхронные ответы в сокет.
  • requestQueue c TTL 600с + DLX ai.dlx: «зависшие» запросы уходят в dead-letter — стоит мониторить ai.dlx.