Обмен сообщениями: 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Очереди RabbitMQ
Заголовок раздела «Очереди RabbitMQ»| Обмен → Очередь | Продюсер | Консьюмер | Особенности |
|---|---|---|---|
requestExchange → requestQueue | ai-agent-service | внешний Walrider | TTL 600с, dead-letter exchange ai.dlx |
responsesExchange → responsesQueue | внешний Walrider | ai-agent-service | routing 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).
WebSocket API (Socket.IO)
Заголовок раздела «WebSocket API (Socket.IO)»- Namespace:
/agent-chat - Комнаты:
project:{projectId}(один тред = один проект) - Авторизация: JWT +
projectIdв query handshake
| Событие | Направление | Payload |
|---|---|---|
connection / disconnect | — | жизненный цикл сокета |
sendMessage | client → server | { content } |
messageSent | server → client | { messageId } (ack) |
message | server → 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 и полеplan— walrider.
Эксплуатационные заметки
Заголовок раздела «Эксплуатационные заметки»- Для
ai-agent-serviceобязателен доступ к RabbitMQ и Redis (кроме PostgreSQL). Без Redis не доставляются асинхронные ответы в сокет. requestQueuec TTL 600с + DLXai.dlx: «зависшие» запросы уходят в dead-letter — стоит мониторитьai.dlx.