1

I am trying to use rascal.js with my node.js app to publish messages via RabbitMQ.

To simplify things:

I got the standard rascal.js file which looks similar to their docs. And I got a controller.js file which receives http request for saving some data. Then this controller.js file calls 2 functions on different files. "SendMail" and "NotifyUser". Both of those functions needs to publish messages to specific queues.

The question how can I access the Rascal.js publish logic from those 2 files? I could not find any examples. Maybe the publish logic suppose to be activated differently? By triggers or events of sort?

And so far the only solution I could use was creating another separate function in my rascal.js file which opens a connection specifically for publishing. It uses input params to determine the name of the queue and the message to be published to it and at the end it closes the connection. This seems to be a bad solution since every request will open a new connection with rascal.js.

this is my first post in this subject - How to manage publish connection per request on rabbitmq(rascal.js)

lifeisfoo
  • 15,478
  • 6
  • 74
  • 115
Ivgi
  • 541
  • 1
  • 6
  • 21

2 Answers2

2

If you're using an express like http server (with middlewares) you can bind the broker to each request object and the use it in your controller code.

This is an example code using express:

your-app.js file:

// import your controller functions
const signup = require('./controller')

let broker = null;

(async () => {
  try {
    broker = await Broker.create(config);
    // your broker setup logic
})();

// your http app setup logic...
app = express(); 

//add the broker to each request object
app.use((req, res, next) => {
  req._broker = broker;
  next();
});

app.use('/signup', signup);

controller.js file:

module.exports = (req, res, next) => {
  // TODO: your controller logic here
  // send the message using the available broker
  req._broker.publish('send_email', 'Hello new user!');
  next();
});
lifeisfoo
  • 15,478
  • 6
  • 74
  • 115
2

Hello I've found another way to handle this, you can do it using "amqplib-as-promised" instead.

Just create a controller like this:

const { Connection } = require('amqplib-as-promised');


class AmqpController {
    async connect() {
        try {
            const connection = new Connection(process.env.CLOUDAMQP_URL)
            await connection.init()
            this.channel = await connection.createChannel()
            console.log("Rabbit connected")
        } catch (error) {
            console.log(error);
        }
    }

    async publish({ queue, type, message, user }) {
        try {
            const payload = { ...message, generatedIn: moment().toDate() }
            this.channel.sendToQueue(
                queue,
                Buffer.from(JSON.stringify(payload)),
                {
                    persistent: true,
                    contentType: "application/json"
                }
            )
        } catch (error) {
            console.log(error)
        }
    }
}
module.exports = new AmqpController()

Then in your app.js / server.js

const AmqpController = require("./controllers/amqp-controller");
AmqpController.connect();

And finally call it from your controller / router implementation like this

const ampqController = require("./amqp-controller");

 ampqController.publish({
        message: articulo,
        type: "",
        queue: 'cm.publisher'
      })

It works smooth for me, since is a class the instance is shared across the app.