npm package: @heavybit/hb-queue-publisher-package
Description: Shared queue publisher package that allows microservices to publish to Rabbit MQ queues
Author: Nicholas Kute
Latest version: 1.0.7

# Introduction

The RabbitMQPublisher package is a lightweight Node.js library designed to simplify message publishing to RabbitMQ queues. This package abstracts the complexities of establishing a RabbitMQ connection, creating channels, and managing queues, allowing developers to integrate RabbitMQ into their microservices with minimal effort.

# Features

- **Persistent RabbitMQ Connection:** Establishes and maintains a persistent connection to RabbitMQ for reliable messaging.
- **Durable Queues:** Publishes messages to durable queues to ensure messages are not lost.
- **Retry Logic with Exponential Backoff:** Automatically retries message publishing with configurable retry attempts and delay.
- **Error Handling:** Gracefully handles connection failures and channel closures.
- **Close Connection and Channel:** Provides a clean method to close the connection and channel when done.

# Technologies Used
- **Node.js**: The core runtime environment for building the package.
- **RabbitMQ**: A message broker for sending messages between microservices.
- **amqplib**: A Node.js library for working with RabbitMQ.

# Installation
You can install the package via npm by running the following command:

`npm install @heavybit/queue-publisher-package`

# Requirements
- Node.js version 12 or higher.
- RabbitMQ installed locally or accessible via a cloud instance.


# Usage

Here’s how to integrate the RabbitMQPublisher package into your project:

1. Import the Package
First, import the RabbitMQPublisher class into your Node.js application:

`const RabbitMQPublisher = require('@heavybit/queue-publisher-package');`

2. Initialize the Publisher
Create an instance of the RabbitMQPublisher:

`const publisher = new RabbitMQPublisher();`

3. Publish Messages to a Queue
To publish a message to a RabbitMQ queue, use the publishToQueue method. This method will automatically establish a connection to RabbitMQ, create the queue if it doesn't exist, and send the message.

```
const queueName = 'myQueue';
const message = { text: 'Hello RabbitMQ!' };

(async () => {
  try {
    await publisher.publishToQueue(queueName, message);
    console.log('Message published successfully');
  } catch (error) {
    console.error('Failed to publish message:', error);
  } finally {
    await publisher.close(); // Close connection and channel after publishing
  }
})();
``` 

4. Configuring RabbitMQ Connection
The package allows connection to RabbitMQ using environment variables. By default, it will connect using the `RABBITMQ_HOST` and `RABBITMQ_PORT` environment variables. Optionally, you can specify the `RabbitMQ_USER` and `RabbitMQ_PASSWORD` if the rabbit MQ setup requires authentication.

```
# Example environment variables
RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest
```

# Retry Logic
The `publishToQueue` method supports automatic retries with exponential backoff. You can configure the maximum number of retries and the initial delay between retries.

```
const retries = 5; // Retry up to 5 times
const initialDelay = 2000; // Initial delay of 2 seconds

(async () => {
  try {
    await publisher.publishToQueue('myQueue', { text: 'Retry test' }, retries, initialDelay);
    console.log('Message published successfully');
  } catch (error) {
    console.error('Failed to publish message after retries:', error);
  }
})();
```

# Closing the RabbitMQ Connection Automatically
Once the message is successfully published, the RabbitMQPublisher automatically closes the connection and channel. You don’t need to explicitly manage connection closures as this is handled internally after message publishing is done, even in case of retries or failures.

If you still want to close the connection manually (e.g., for cleanup purposes), you can use the close method:

```
rabbitMQPublisher.close()
  .then(() => console.log("RabbitMQ connection closed"))
  .catch((error) => console.error("Error closing RabbitMQ connection:", error));
```

# Example with Manual Connection Closure
In most cases, you won’t need to manually close the connection. However, for advanced cases, here’s how to do it:

```
(async () => {
  try {
    const rabbitMQPublisher = new RabbitMQPublisher();
    
    // Manually connect and publish a message
    await rabbitMQPublisher.connect();
    const data = { message: "Manual connection closure example" };
    await rabbitMQPublisher.publishToQueue("my_queue", data);

    // Manually close the connection
    await rabbitMQPublisher.close();
    console.log("Connection closed manually.");
  } catch (error) {
    console.error("An error occurred:", error);
  }
})();
```

# Example: Integrating into a Microservice
Here's how you can integrate RabbitMQPublisher into a Node.js microservice to publish messages to RabbitMQ queues:

```
const express = require('express');
const RabbitMQPublisher = require('@heavybit/queue-publisher-package');

const app = express();
const publisher = new RabbitMQPublisher();

app.use(express.json());

app.post('/send-to-queue', async (req, res) => {
  const { queueName, message } = req.body;
  
  try {
    await publisher.publishToQueue(queueName, message);
    res.status(200).send('Message sent to RabbitMQ');
  } catch (error) {
    console.error('Failed to send message:', error);
    res.status(500).send('Failed to send message');
  }
});

app.listen(3000, () => {
  console.log('Microservice running on port 3000');
});
```

# API Reference

`RabbitMQPublisher.connect()`

Establishes a connection to the RabbitMQ server. This method is automatically called when you attempt to publish a message.

**Returns:**
- `Promise<void>`

**Throws:**
- Error if the connection to RabbitMQ fails.

---

`RabbitMQPublisher.publishToQueue(queueName, data, retries = 3, initialDelay = 1000)`

Publishes a message to the specified RabbitMQ queue with retry logic and exponential backoff.

**Parameters:**
- `queueName (string)`: The name of the RabbitMQ queue.
- `data (Object)`: The message payload to be sent to the queue.
- `retries (number)`: The maximum number of retry attempts (default is 3).
- `initialDelay (number)`: The initial delay (in milliseconds) before retrying (default is 1000 ms).

**Returns:**
- `Promise<void>`

**Throws:**
- Error if queueName or data is missing.
- Error after all retry attempts fail.

---

`RabbitMQPublisher.close()`

Closes the RabbitMQ channel and connection. This method is automatically called after message publishing is completed. You can also call it manually if needed.

**Returns:**
- `Promise<void>`

---