Skip to navigation

Fastify Azure Service Bus

This is a proof of concept on how to implement fastify with azure service bus within docker. This poc also follows code folder structure set by the team.


Pre-requisite

  1. Connect to Linux VM via SSH by running the power shell script.
  2. Add a queue named “message-queue” in your Azure Service Bus
  3. Pull the lts:node docker image before proceeding. If not, run below command
docker image pull node:lts

Initialization

Steps:

  1. Create a working directory
mkdir <your project name>
cd <your project name>
  1. Run and create a container
docker run -it -v `pwd`:`pwd` -w `pwd` -p 127.0.0.1:3000:4000 node:lts sh
  1. Initialize the node project
npm init -y
  1. Install packages and Dependencies
npm i fastify dotenv @azure/service-bus
npm i -D typescript @types/node
npm i nodemon
  1. Initialize tsconfig.json file
npx tsc --init
  1. Add a new script in package.json
npm pkg set "scripts.dev"="node -w & nodemon src/server.ts" -f
  1. Add code to your project

.env

AZURE_SERVICE_BUS_CONNECTION_STRING=<azure service bus primary connection string>
PORT= <port which app will run>

src\api\controllers\messageController.ts

import { FastifyReply, FastifyRequest } from 'fastify';
import azureServiceBusService from '../../services/azureServiceBusService';
import { MessageRequest } from '../../types/message';
const sendMessage = async (req: FastifyRequest<{ Body: MessageRequest }>, reply: FastifyReply) => {
await azureServiceBusService.sendMessageToQueue('message-queue', req.body);
return reply.send({ status: 'Message sent' });
};
const receiveMessages = async (req: FastifyRequest<{ Body: MessageRequest }>, reply: FastifyReply) => {
// await azureServiceBusService.receiveMessagesFromQueue('message-queue');
return reply.send({ status: 'Message received' });
};
const getMessage = async (req: FastifyRequest , reply: FastifyReply) => {
return reply.send({ 'hello': 'world'});
}
export default { getMessage, sendMessage, receiveMessages };

src\api\routes\messageRoutes.ts

import { FastifyInstance } from 'fastify';
import messageController from '../controllers/messageController';
export default async function messageRoutes(fastify: FastifyInstance) {
// message
fastify.get('/', messageController.getMessage);
fastify.post('/send', messageController.sendMessage);
fastify.post('/receive', messageController.receiveMessages);
// other
}

src\api\routes\index.ts

import { FastifyInstance } from "fastify";
export default async function allRoutes(fastify: FastifyInstance) {
fastify.register(require('./messageRoutes'))
}

src\config\index.ts

import dotenv from 'dotenv';
dotenv.config();
export default {
port: process.env.PORT || 3000,
azureServiceBusConnectionString: process.env.AZURE_SERVICE_BUS_CONNECTION_STRING || '',
};

src\plugins\azureServiceBusPlugin.ts

import { ServiceBusClient } from '@azure/service-bus';
import config from '../config/index';
let client: ServiceBusClient;
const azureServiceBusPlugin = async function (fastify: any) {
try {
client = new ServiceBusClient(config.azureServiceBusConnectionString);
fastify.decorate('azureServiceBus', client);
fastify.log.info('🚀 Azure Service Bus Connected');
} catch (err) {
fastify.log.error('❌ Azure Service Bus Connection Error:', err);
process.exit(1);
}
};
export default azureServiceBusPlugin;
export { client };

src\services\azureServiceBusService.ts

import { ServiceBusClient } from '@azure/service-bus';
import config from '../config/index';
const client = new ServiceBusClient(config.azureServiceBusConnectionString);
const sendMessageToQueue = async (queueName: string, message: object) => {
try {
const sender = client.createSender(queueName);
await sender.sendMessages({ body: JSON.stringify(message) });
console.log(`Message sent to Azure Service Bus queue: ${queueName}`);
} catch (error) {
console.error('Error sending message to Azure Service Bus:', error);
}
};
const receiveMessagesFromQueue = async (queueName: string) => {
try {
const receiver = client.createReceiver(queueName);
const queueMessages = await receiver.receiveMessages(10);
for(var i = 0; i != queueMessages.length; i++){
console.log(`Message received from Azure Service Bus queue: ${queueName} with message ${queueMessages[i]}`);
await receiver.completeMessage(queueMessages[i]);
}
} catch (error) {
console.error('Error receiving message to Azure Service Bus:', error);
}
};
export default { sendMessageToQueue, receiveMessagesFromQueue };

src\types\message.d.ts

export interface MessageRequest {
text: string;
userId: string;
}

src\server.ts

import Fastify from 'fastify';
import routes from './api/routes/index';
import azureServiceBusPlugin from './plugins/azureServiceBusPlugin';
const fastify = Fastify({ logger: true });
// Register plugins
fastify.register(azureServiceBusPlugin);
// Register routes
fastify.register(routes);
const start = async () => {
try {
await fastify.listen({ port: 3000, host: 'localhost' });
fastify.log.info(`Server running on port ${fastify.server.address()}`);
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();

Running the application

To run the application, execute below command while on docker run. This will run on http://localhost:3000

npm run dev

Test the api

  1. Sending a message to Azure Service Bus
curl -H 'Content-Type: application/json' \
-d '{ "message": "This is send message." }' \
-X POST \
http://localhost:3000/send
  1. Read the message in Azure Service Bus
curl -X POST \
http://localhost:3000/Receive

Verification

Connect to Azure Service Bus and look for the queue in which the message was sent.