circuit

How to Talk to a RabbitMQ Instance with Node.js and TypeScript

RabbitMQ, Node.js, and TypeScript all together




RabbitMQ is a message queue system that allows you to queue messages (string values that have a meaning for your application) to be consumed by consumers (pieces of programs made to treat RabbitMQ messages).

It can be used when there is a lot of data to process but their treatment doesn’t have to be instant.

In this article, we are going to set up a Node.js application that can send and consume messages with a RabbitMQ instance.

Prerequisites

We are not going to spend too much time setting up RabbitMQ. Instead, we are going to use the docker image of RabbitMQ.

To do so, you’ll need to have Docker installed and running on your machine.

We are also going to work with Node.js, you’ll have to have npm installed with or without NVM. Version 14 or newer will be enough!

Skyrocket RabbitMQ with docker-compose

We don’t want to waste time configuring RabbitMQ. Instead, we are going to use Docker to quickly deploy RabbitMQ.

In your project, create a docker-compose.yml file and paste the following content in it:

version: "3.7"
services:
  rabbitmq:
    image: rabbitmq:3.9.13-management-alpine
    container_name: 'rabbitmq'
    restart: always
    environment:
      - "RABBITMQ_DEFAULT_PASS=password"
      - "RABBITMQ_DEFAULT_USER=username"
    ports:
      - 15672:15672
      - 5672:5672
    networks:
      - rabbitmq_go_net

networks:
  rabbitmq_go_net:
    driver: bridge

Then in a terminal, just run the command docker-compose up -d It’ll deploy a new running instance of RabbitMQ!

Once done, open in your browser http://localhost:15672 and use the username and password provided in the docker-compose file.

You should be seeing the management page of RabbitMQ! Don’t hesitate to have a quick look around if you are not familiar with it.

Make the connection with RabbitMQ

To do so, we are going to use a library called amqplib which is a RabbitMQ client for Node.js. amqplib *npm install amqplib A library for making AMQP 0-9-1 clients for Node.JS, and an AMQP 0-9-1 client for Node.JS v10+…*www.npmjs.com

Install it and also install its type definition (If you are not using TypeScript, you don’t need to).

npm install amqplib -S
npm install @types/amqplib -D

Once installed, we’ll connect to the RabbitMQ instance.

The library supports 2 methods (async or callback) we are going to use async here. If you want to enable the callback one, just add /callback_api at the end of each import.

import client, {Connection} from 'amqplib'

...

const connection: Connection = await client.connect(
  'amqp://username:password@localhost:5672'
)

This is the first step for using RabbitMQ, the connection to the service. The URL is using the same user/password defined in the docker-compose file. The port is the second one in the configuration file: 5672

The connection object is returned by the async function connect.

Send messages to RabbitMQ

The second step is going to be sending messages to our RabbitMQ service.

We’ll have to access our queue for that. Queues are automatically created when accessed for the first time, there is no need to worry about their existence.

We’ll first have to create a channel. A channel is a lightweight TCP connection that is used to send/receive data to/from RabbitMQ. They coexist with the connection and are closed if the connection is closed.

const connection: Connection = await client.connect(
'amqp://username:password@localhost:5672'
)

// Create a channel
const channel: Channel = await connection.createChannel()

// Makes the queue available to the client
await channel.assertQueue('myQueue')

//Send a message to the queue
channel.sendToQueue('myQueue', ***Buffer***.from('message'))

After adding this code to your program, you should have a look at your management page and especially the queues tab.

If everything worked as expected, you should see a queue called myQueue (or whatever you called it) and if you open it, it’ll have one message in idle mode. This message is awaiting to be consumed. That is the next and last step of our article.

Consume our messages

Consuming messages is fairly simple. All we have to do is use the channel to call the consume method and give it the queue to consume and the callback to be called when receiving a message.

You should create small pieces of programs dedicated to consuming instead of adding the consumers to the main application. The reason is that javascript is monothreaded and the consumers could slow down the main application if they were receiving intensive jobs to solve.

import client, {Connection, Channel, ConsumeMessage} from 'amqplib'

// Function to send some messages before consuming the queue
const sendMessages = (channel: Channel) => {
  for (let i = 0; i < 10; i++) {
    channel.sendToQueue('myQueue', ***Buffer***.from(`message ${i}`))
  }
}

// consumer for the queue.
// We use currying to give it the channel required to acknowledge the message
const consumer = (channel: Channel) => (msg: ConsumeMessage | null): void => {
  if (msg) {
    // Display the received message
    ***console***.log(msg.content.toString())
    // Acknowledge the message
    channel.ack(msg)
  }
}

const connection: Connection = await client.connect(
'amqp://username:password@localhost:5672'
)
// Create a channel
const channel: Channel = await connection.createChannel()
// Makes the queue available to the client
await channel.assertQueue('myQueue')
// Send some messages to the queue
sendMessages(channel)
// Start the consumer
await channel.consume('myQueue', consumer(channel))

Here is our final code! This piece of code is going to create/access our queue, send some messages on it and consume it.

You may notice a call to channel.ack this is required to tell RabbitMQ that the message has been processed with success. Otherwise, RabbitMQ will await for it to be done and republish it eventually (is you set it up like this).

Conclusion

You should now have a working RabbitMQ client on your Node.js application.

If you’d like to learn more about the API of amqplib, you should out check their documentation.

You can find the code of the article on my GitHub.

I hope you liked this article! Take care!




Continue Learning