In this post, we will learn how to create a NestJS RabbitMQ Microservice from scratch. Basically, this involves using the RabbitMQ Transporter.

RabbitMQ is one of the most popular message brokers out there. It is used worldwide from small startups to large enterprises. It is also open-source, lightweight and supports several message protocols. Also, we can deploy RabbitMQ in distributed environments to ensure high-availability and scalability.

1 – Installation

The first step is to install the packages. Below commands will do the same:

$ npm i --save @nestjs/microservices
$ npm i --save amqplib amqp-connection-manager

The first command installs the NestJS Microservices package. If you wish to know more about it, refer to this post on creating a NestJS Microservice. The second command installs the packages necessary to create RabbitMQ based microservices.

Also, we need a RabbitMQ broker. The fastest way to get that running is by using Docker. We can spawn a RabbitMQ container with the below command.

$ docker run -d --hostname demo-rabbit -p 5672:5672 -p 15672:15672 --name demo-rabbit rabbitmq:3-management

We specifically use the rabbitmq:3-management image. This will enable the RabbitMQ management console. Also, we expose two ports 5672 and 15672. Once the containers starts up, we can login to the management console (http://localhost:15672) using the user id guest and password guest.

By the way, if you are interested in Backend frameworks and concepts, you’d love my weekly newsletter where I cover such concepts in a fun & interesting manner.

2 – Configuring the NestJS RabbitMQ Microservice

To use the RabbitMQ transporter, we pass the options object to the createMicroservice() method of the NestFactory class. See below code from the greeting-service:

import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
    transport: Transport.RMQ,
    options: {
      urls:['amqp://localhost:5672'],
      queue: 'books_queue',
      queueOptions: {
        durable: false
      }
    }
  })
  await app.listen();
}
bootstrap();

Here, we specify the transport property using the Transport.RMQ enum. Also, we provide the options such as url for our RabbitMQ broker, the name of the queue we would like the service to listen to and some queue options.

The queue we mention in the options object is automatically created for us when we start the application. See below screenshot where we can see the books_queue.

nestjs rabbitmq microservice

3 – Subscribing in NestJS RabbitMQ Microservice

We can now subscribe to messages or events within our service. See below code:

import { Controller } from '@nestjs/common';
import { EventPattern, MessagePattern } from '@nestjs/microservices';

@Controller()
export class AppController {

  @MessagePattern({cmd: 'greeting'})
  getGreetingMessage(name: string): string {
    return `Hello ${name}`;
  }

  @MessagePattern({cmd: 'greeting-async'})
  async getGreetingMessageAysnc(name: string): Promise<string> {
    return `Hello ${name} Async`;
  }

  @EventPattern('book-created')
  async handleBookCreatedEvent(data: Record<string, unknown>) {
    console.log(data);
  }

}

Basically, we use the @MessagePattern and @EventPattern decorators to listen to messages. You can read more about these decorators in our posts on NestJS Microservice using Request Response approach and Event-Based NestJS Microservice.

However, for this post, just think of these decorated methods as handlers for specific type of messages or events.

4 – Publishing a Message or Event

The next step is to publish a message or event from another service or client application. To do so, we have to install the same packages as we did in the first section. Next, we have to configure the client application to talk to the RabbitMQ message broker.

See below code:

import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    ClientsModule.register([{
      name: 'GREETING_SERVICE',
      transport: Transport.RMQ,
      options: {
        urls: ['amqp://localhost:5672'],
        queue: 'books_queue',
        queueOptions: {
          durable: false
        }
      }
    }])
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Basically we use the register() method of the ClientsModule to register our RabbitMQ broker. Also, we specify a token name as GREETING_SERVICE for our greeting-service. This token helps us inject this service wherever we want to use it in our application. See below example:

import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';

@Injectable()
export class AppService {

  constructor(@Inject('GREETING_SERVICE') private client: ClientProxy){}

  async getHello(){
    return this.client.send({cmd: 'greeting'}, 'Progressive Coder');
  }

  async getHelloAsync() {
    const message = await this.client.send({cmd: 'greeting-async'}, 'Progressive Coder');
    return message;
  }

  async publishEvent() {
    this.client.emit('book-created', {'bookName': 'The Way Of Kings', 'author': 'Brandon Sanderson'});
  }
}

As you can see, we use @Inject() decorator to inject the greeting-service using ClientProxy. Next, we use the send() and emit() methods to send messages or publish events. These events are then routed to the broker (specifically books_queue) from where our greeting-service gets those messages and acts on them appropriately.

Conclusion

With this, we have successfully learnt how to create a NestJS RabbitMQ Microservice. We configured the RabbitMQ transporter and spawned a RabbitMQ broker using Docker to build our application.

The code for this application is available on Github for reference.

If you have any comments or queries, please mention in the comments section below.

Anyways, before we end this post, a quick reminder about the Progressive Code Newsletter where I explain Backend frameworks & concepts in a fun & interesting manner so that you never forget what you’ve learned.

I’m 100% sure you’d love it.

Subscribe now and see you over there.

Categories: BlogNestJS

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *