ADR-0015: Мульти-протокольный public API (REST + gRPC + WebSocket)
Status: accepted Date: 2026-04-17 Deciders: команда проекта
Контекст
Клиенты системы — разнородные: web/mobile UI, B2B-интеграции, realtime-индикаторы. Один протокол не покрывает все нужды:
- REST/JSON удобен для UI и простых интеграций.
- gRPC даёт типизированные контракты, эффективную сериализацию и server streaming для крупных операций (B2B).
- WebSocket — для realtime подписок и статусов async jobs.
Также пользовательское требование: “запрашивать кеш и актуализацию данных, получать апдейты в realtime” — единая семантика на всех трёх протоколах.
Решение
Новый сервис public-api, экспонирующий бизнес-операции по трём протоколам поверх общего ядра use cases.
- Application layer (use cases) общий, transport-specific только в
api/{rest,grpc,ws}/. - REST — описан OpenAPI 3.1.
- gRPC — описан .proto.
- WS — описан AsyncAPI; subscription model (один conect, мультиплексирование).
- Все ответы содержат freshness metadata (см. P20).
- Семантика: read cache (GET / unary RPC / WS subscribe-with-snapshot), trigger refresh (POST / unary RPC создаёт EnrichmentJob), watch updates (polling / server stream / WS subscription).
Реализация зафиксирована:
- один edge-server на
net/http+http.ServeMux; - RPC-слой — Connect (protobuf contracts, поддержка Connect/gRPC/gRPC-Web);
- WebSocket-слой —
github.com/coder/websocket; - внутренние вызовы в core-сервисы — по internal HTTP/Connect endpoint’ам через
docker-composenetwork.
Конкретный runtime stack детализирован в ADR-0021.
Последствия
Плюсы
- Один источник истины бизнес-логики (use cases).
- Каждый клиентский класс получает свой удобный протокол.
- Realtime через WS без bolt-on решений.
- Унифицированная cache+actualize модель.
Минусы
- Тройная поверхность для тестирования и документации.
- WS — отдельный operations-aspect (connection state, reconnect, scaling).
- Усложнение auth (JWT валиден для трёх стеков).
- Backpressure требует осознанного дизайна для WS.
Нейтральные последствия
- Все три протокола поддерживают одни Visibility Policies, freshness metadata, EnrichmentJob интеграцию.
Рассмотренные альтернативы
Только REST + SSE
SSE — слабее WS (только server→client), проще но менее гибкий. Не закрывает gRPC use cases (B2B integrations).
Только gRPC + gRPC-Web
Не закрывает удобный REST-контур для web/mobile и простых интеграций.
REST + WS, без gRPC
Не удовлетворяет B2B-кейсы с типизированными контрактами и streaming.