Gateway
Назначение
gateway — публичный HTTP-вход в систему на NestJS. Сервис принимает REST-запросы, публикует Swagger на /api и проксирует операции во внутренние сервисы:
auth-serviceчерез RabbitMQ RPCpersonnel-serviceчерез RabbitMQ RPCproduction-serviceчерез RabbitMQ RPCetl-serviceчерез прямой HTTP proxy
Сам gateway не содержит собственной предметной модели и не хранит бизнес-данные. Его роль — аутентификация входящих запросов, валидация DTO, нормализация ошибок и проксирование вызовов дальше по системе.
Основные модули
AppModule
Поднимает глобальные инфраструктурные возможности:
ConfigModuleкак глобальный источник конфигурацииCacheModuleс TTL10000ThrottlerModuleс тремя профилями лимитов:short:20 req / 1smedium:100 req / 10slong:500 req / 60sLoggerModule(nestjs-pino) с pretty/file transport в non-production- глобальные
LoggingInterceptor,AllExceptionsFilter,ThrottlerGuard RequestIdMiddlewareдля всех маршрутов
SecurityModule
Собирает JWT-проверку и ролевую авторизацию:
JwtModuleсJWT_ACCESS_SECRET,JWT_ACCESS_TTL,JWT_ACCESS_ISSUERAuthGuard:- извлекает Bearer token из
Authorization - валидирует JWT
- при наличии
AUTH_USER_RESOLVERдогружает профиль пользователя изauth-service - кэширует resolved user на
30s RoleGuardпроверяет роли из декоратора@Auth(...)AuthProxyServiceзарегистрирован какAUTH_USER_RESOLVER
Доменные HTTP-модули
AuthModule- контроллеры
AuthControllerиUsersController - маршруты аутентификации и администрирования пользователей
PersonnelModulePersonnelController+PersonnelProxyService- маршруты по подразделениям, должностям, сотрудникам и шаблонам смен
ProductionModuleProductionController+ProductionProxyService- маршруты по продуктам, заказам, выпуску, продажам, остаткам, качеству, датчикам, KPI
EtlModuleEtlController+EtlProxyService- HTTP proxy в ETL API, включая multipart upload и file download
RabbitModule
Подключает @golevelup/nestjs-rabbitmq через getRMQConfig():
AMQP_URIберется из конфигурацииprefetchCount = 32- publish persistent
connectionInitOptions.wait = false- очереди создаются как quorum (
x-queue-type = quorum)
Внешний API
Аутентификация и пользователи
Контроллеры:
POST /api/auth/registerPOST /api/auth/loginGET /api/auth/mePOST /api/auth/refresh-sessionGET /api/usersPATCH /api/users/:userIdPOST /api/users/deactivate
Особенности:
loginиrefresh-sessionвыставляютhttpOnlycookierefreshTokenregisterиloginимеют отдельные throttling-лимитыGET /auth/meопирается наAuthGuard, который после валидации JWT догружает пользователя изauth-service- часть маршрутов ограничена ролями через
@Auth(...) GET /usersв коде помечен как admin-only по Swagger/описанию, но decorator@Auth(UserRole.ADMIN)сейчас закомментирован
Personnel API
PersonnelController публикует CRUD/queries для:
- подразделений
- должностей
- сотрудников
- шаблонов смен
Маршруты защищены ролями ADMIN, MANAGER, SHIFT_MANAGER, ANALYST в зависимости от операции.
Production API
ProductionController публикует операции для:
- продуктов
- производственных заказов
- выпуска продукции
- продаж и их сводки
- складских остатков
- результатов контроля качества
- показаний датчиков
- KPI
Контроллер оформлен как публичный HTTP фасад поверх ProductionProxyService.
ETL API
EtlController проксирует запросы в отдельный ETL HTTP API:
POST /api/etl/importPOST /api/etl/import/fileGET /api/etl/importsGET /api/etl/imports/:idGET /api/etl/imports/:id/filePOST /api/etl/imports/:id/retry
Особенности:
- требуется роль
ADMIN - при file import используется
FileInterceptor - максимальный размер файла:
20 MB - проксируются
x-request-id,x-user-id,x-user-roleи входящийAuthorization
Интеграции
RabbitMQ
AuthProxyService, PersonnelProxyService и ProductionProxyService отправляют RPC-запросы через amqpConnection.request(...).
Используемые exchanges по коду:
efko.auth.commandsefko.auth.queriesefko.auth.eventsefko.personnel.commandsefko.personnel.queriesefko.production.commandsefko.production.queries
Ключевые auth RPC topics:
AuthRegisterUserCommand.topicAuthLoginUserCommand.topicAuthRefreshSessionCommand.topicAuthGetCurrentUserQuery.topicAuthGetUsersQuery.topicAuthUpdateUserCommand.topicAuthDeactivateUserCommand.topic
Personnel и Production используют аналогичную схему: отдельные command/query topics из @efko-kernel/contracts.
Каждый proxy:
- пробрасывает request metadata через
buildRpcHeadersFromRequest - логирует начало, завершение, rejected и failed исхода
- ставит timeout на RPC через
requestWithTimeout(...)
HTTP-интеграция с ETL
EtlProxyService обращается к ETL_SERVICE_URL и по умолчанию использует внутренний адрес сервиса. Внешний маршрут всегда собирается как /api/v1/.... Ошибки downstream HTTP разворачиваются в HttpException, при недоступности возвращается 503.
Обработка ошибок
HTTP слой
- глобально подключен
HttpExceptionFilterвmain.ts - в
AppModuleдополнительно зарегистрированAllExceptionsFilter - валидация DTO выполняется глобальным
ValidationPipeсtransform,whitelist,forbidNonWhitelisted
Нормализация RPC ошибок
Proxy-сервисы ожидают либо успешный payload, либо RpcErrorResponse. Для auth-кодов есть явное сопоставление:
USER_ALREADY_EXISTS->409USER_NOT_FOUND->404INVALID_CREDENTIALS->401REFRESH_TOKEN_*->401/404- неизвестные коды падают в
HttpExceptionчерез общий mapper
Если RPC не отвечает, requestWithTimeout(...) выбрасывает GatewayTimeoutException.
ETL ошибки
ETL proxy:
- возвращает downstream status/code, если тот пришел от ETL
- возвращает
503 ETL service unavailable, если соединение не удалось
Observability и logging
nestjs-pinoиспользуется как основной HTTP logger- в dev-режиме пишется файл
logs/gateway.log RequestIdMiddlewareприсваиваетrequestIdLoggingInterceptorлогирует HTTP-запросы и latencyAuthProxyServiceи другие proxy-сервисы дополнительно логируют RPC lifecycle (started,completed,rejected,failed)- Swagger поднимается на
/api, JSON — на/api/swagger/json
Хранение данных
Собственного persistence слоя в gateway нет:
- нет Prisma/TypeORM/Mongoose модулей
- кэш используется только как инфраструктурный слой для resolved user в
AuthGuard - stateful часть сведена к cookie
refreshTokenна HTTP-ответе и краткоживущему cache entry
Роль в системе
gateway связывает пользовательский HTTP-интерфейс и внутреннюю микросервисную шину:
- проводит аутентификацию по access token
- выполняет coarse-grained авторизацию по ролям
- унифицирует контракты и ошибки для внешних клиентов
- консолидирует доступ к нескольким backend-сервисам через единый REST API
Допущения и пробелы по коду
gatewayявно зависит отproduction-service, ноgetRMQConfig()в текущем коде декларирует exchanges/queues только дляauthиpersonnel; production exchanges в конфиге не зарегистрированы.GET /api/usersописан как admin-only, но защита роли сейчас отключена комментарием.- В сервисе нет собственного health endpoint; доступность downstream определяется только по факту proxy-вызова.