NestJS NATS запрос-ответ

Я пытаюсь использовать NestJS и микросервис NATS. Есть хороший документация для настройки базового запроса-ответа.

Я сделал следующее:

Запустил локальный сервер NATS.

Настройте мой main.ts для подключения к серверу:

async function bootstrap() {
  const app = await NestFactory.createMicroservice(AppModule, {
    options: {
      url: "nats://localhost:4222",
    },
    transport: Transport.NATS,
  });
  app.listen(() => console.info("Microservice is listening"));
}
bootstrap();

Создал ClientProxyFactory для отправки обратных сообщений:

export const NatsClientProvider: Provider = {
  inject: [ConfigService],
  provide: NatsClientProviderId,
  useFactory: async (config: ConfigService) =>
    ClientProxyFactory.create({
      options: {
        servers: config.getNatsConfig().servers,
      },
      transport: Transport.NATS,
    }),
};

Настройте контроллер app.controller.ts, чтобы он реагировал на определенный шаблон:

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    @Inject(NatsClientProviderId) private readonly natsClient: ClientProxy,
  ) {}

  @MessagePattern("hello")
  async getHello(data: string) {
    console.info("data: ", data);
    console.info("getHello!!");
    await this.natsClient.send("hello", this.appService.getHello());
    return this.appService.getHello();
  }

  async onModuleInit() {
    await this.natsClient.connect();
    console.info("Nats connected!");
  }

Настройте тестовый файл, чтобы попытаться отправить сообщение запрос-ответ:

import { connect } from "ts-nats";

async function start() {
  const nc = await connect({
    servers: ["nats://localhost:4222"],
  });

  const msg = await nc.request("hello", 5000, "me");
  console.info("msg: ", msg);
}

start();

Когда я запускаю приложение Nest, я вижу правильно созданную подписку в журналах сервера NATS.

Когда я запускаю файл test.ts, время ожидания истекает с NatsError: Request timed out.. Тем не менее, я могу видеть свои журналы консоли (хотя данные undefined, хотя я указываю это в опубликованном сообщении.

Ни return, ни client.send методы не работают для получения сообщений от приложения.

Любая помощь приветствуется!

Обновлено: Все еще изучаю и застрял в этом вопросе. В разделе «Отправка сообщений» Документы по микросервису говорится: «Шаблон должен быть равен шаблону, определенному в декораторе @MessagePattern(), а полезная нагрузка — это сообщение, которое мы хотим передать другому микросервису». Если я это сделаю, приложение Nest обнаружит сообщение, которое оно отправляет, и застрянет в бесконечном цикле отправки сообщения и получения одного и того же сообщения туда и обратно навсегда.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
6
0
4 976
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

При использовании ClientProxy send и emit возвращают Observables. Вам нужно «активировать» их, чтобы они могли что-то делать. Таким образом, вы можете либо subscribe им, либо изменить его на Обещание.

так как вы используете await вы, вероятно, хотите сделать

await this.natsClient.send("hello", this.appService.getHello()).toPromise();

Хм, спасибо за информацию. Я попробовал это, и я все еще получаю бесконечный цикл, когда служба продолжает отвечать на свое собственное сообщение (похоже, это связано с тем, что сообщение @MessagePattern совпадает с отправляемой темой. Хотя я предполагаю, что это должно быть вот так, чтобы работал запрос-ответ, только не понимаю, как сделать, чтобы он не отвечал сам на себя, так как и ClientProxy, и микросервис Nest подключены к одному и тому же NATS-серверу.

rhlsthrm 14.06.2019 10:55
Ответ принят как подходящий

Чтобы избежать бесконечного цикла в вашем контроллере, удалите оператор natsClient.send. MessagePattern автоматически отправит ответ с данными, которые вы возвращаете из функции, в вашем случае this.appService.getHello():

@MessagePattern("hello")
async getHello(data: string) {
  console.info("data: ", data);
  return "Hello World!";
}

Nest требует, чтобы вы отправили длинный атрибут id (подойдет любая строка), чтобы он мог ответить на сообщение. Просто включите его в данные json:

// Nest expects the data to have the following structure
const reply = await nc.request("hello", 500, JSON.stringify({ data: "Hello", id: "myid" }));
console.info({ reply });

В журнале гнезда вы увидите следующую запись журнала:

data: Hello

В тестовом сценарии вы увидите следующее:

{ reply:
   { subject: '_INBOX.GJGL6RJFYXKMCF8CWXO0HB.GJGL6RJFYXKMCF8CWXO0B5',
     sid: 1,
     reply: undefined,
     size: 50,
     data: '{"err":null,"response":"Hello World!","id":"myid"}' 
} }

Здесь не используется шаблон запроса-ответа: github.com/nats-io/nats.ts. Я просто должен иметь возможность использовать let msg = await nc.request('greeter', 1000, 'me');, который позаботится о полной подписке, публикации и ответе. Вы, возможно, поняли мою проблему с данными, хотя.

rhlsthrm 14.06.2019 18:47

Чтобы уточнить, если я отправлю запрос следующим образом: const msg = await nc.request(JSON.stringify({ cmd: "hello" }),5000,JSON.stringify({data: "me",})); я могу записать в консоль правильные данные, но мое приложение Nest не отправляет ответ обратно.

rhlsthrm 14.06.2019 20:35

Кроме того, я попробовал подход, который вы упомянули, я получаю ответ от тестового сценария, но это тот же сценарий, который получает свое собственное сообщение, и приложение Nest ничего не получает должным образом. Приложению Nest необходимо отправить ответ на мой сервер NATS, который клиент (тестовый сценарий) получает и регистрирует.

rhlsthrm 14.06.2019 20:39

Извините, вы правы, это было неправильно. Пожалуйста, смотрите мое редактирование. Недостающим битом было поле id.

Kim Kern 20.06.2019 18:35

Спасибо за помощь! Есть ли способ также получить тему входного сообщения в Nest? Например, если я хочу подписаться на user.get.>, чтобы получать сообщения на user.get.MY_USER_ID и видеть, что MY_USER_ID было в теме.

rhlsthrm 21.06.2019 15:13

Не то, что я знаю из. :/ Работает ли он даже с подстановочными знаками в гнезде?

Kim Kern 21.06.2019 16:02

Если это не работает с подстановочными знаками, это не для меня. Я обошел эту проблему, реализовав свой собственный общедоступный/подуровень NATS, но мне бы хотелось использовать инфраструктуру Nest. Я открою вопрос с Nest по этому поводу. Спасибо за помощь.

rhlsthrm 21.06.2019 16:07

Я только что проверил, и он действительно работает с подписками с подстановочными знаками, как в приведенном мной примере (@MessagePattern('hello.>') и тема запроса hello.world). Теперь, если я смогу распечатать тему, я буду готов.

rhlsthrm 21.06.2019 16:12

Я не думаю, что это часть API, но вы можете открыть для него вопрос (или даже запрос на извлечение). Не должно быть сложно, я думаю.

Kim Kern 24.06.2019 13:04

Другие вопросы по теме