Home > Back-end >  how to pass a message from go and consuming it from nestjs with rabbitmq?
how to pass a message from go and consuming it from nestjs with rabbitmq?

Time:12-31

I have a go service that publishes a message to rabbitmq and the code which is responsible for that part is as below:

package main

import (
    "log"

    "github.com/streadway/amqp"
)

func main() {
    conn, amqError := amqp.Dial("amqp://localhost:5672/")
    if amqError != nil {
        panic(amqError)
    }

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    q, err := ch.QueueDeclare(
        "default", // name
        true,      // durable
        false,     // delete when unused
        false,     // exclusive
        false,     // no-wait
        nil,       // arguments
    )
    failOnError(err, "Failed to declare a queue")

    body := "{ \"body\":\"Hello...\", \"pattern\":\"test\",  \"age\":\"20\"}"

    err = ch.Publish(
        "",     // exchange
        q.Name, // routing key
        false,  // mandatory
        false,  // immediate
        amqp.Publishing{
            ContentType: "text/plain",
            Body:        []byte(body),
        },
    )
    failOnError(err, "Failed to publish a message")

}

func failOnError(err error, msg string) {
    if err != nil {
        log.Fatalf("%s: %s", msg, err)
    }
}

And the Nestjs part that is consuming the message is as:

import { Controller } from '@nestjs/common';
import { Ctx, EventPattern, Payload, RmqContext } from '@nestjs/microservices';

@Controller()
export class AppController {
  constructor() { }

  @EventPattern("test")
  getEventMessage(@Payload() data: any, @Ctx() context: RmqContext) {
    console.log("data is -> ", data) // always undefined
    console.log(
      "content of message is -> ",
      JSON.parse(
        context.getMessage().content.toString() // from buffer to string
      )
    )
  }
}

Now the problem is that I can't get the message from data instead of parsing it from ctx, also I need to send the message in go as json without skipping double quotes like this "\""

CodePudding user response:

The following is the response to your questions:

  1. In the examples of NextJS they don't provide how to use the payload data, instead of it, they say:

To access the original RabbitMQ message (with the properties, fields, and content), use the getMessage() method of the RmqContext

Given the above statement, you are parsing properly the message in the queue.

  1. Avoiding to do manually the body string to send, you should use a process called json Marhsal of struct, for example:
  • You should create a struct that contains the information to send to queue
  • Marshal struct and generates the []byte

type MessageQueue struct {
    Body    string `json:"body"`
    Pattern string `json:"pattern"`
    Age     string `json:"age"`
    Data    string `json:"data"`
}

func NewMessageQueue(body, pattern, age string, data) *MessageQueue {
    return &MessageQueue{
        body, pattern, age, data
    }
}

func (m *MessageQueue) Marshal() ([]byte, error) {
    bytes, err := json.Marshal(m)

    if err != nil {
        return nil, err
    }
    return bytes, err
}

func main() {
    ...

    message := NewMessageQueue("Hello...", "test", "20", "data...")
    // TODO: check the error
    body, _ := message.Marshal()

    err = ch.Publish(
        "",         // exchange
        q.Name,     // routing key
        false,      // mandatory
        false,      // immediate
        amqp.Publishing{
            ContentType: "text/plain",
            Body:        body,
        },
    )

    ...
}

Update:

  1. The data param received by controller on getEventMessage method, it should be sent on body from Golang to be deserialized by Nestjs. It means the structure should be the following:

type MessageQueue struct {
    Body    string `json:"body"`
    Pattern string `json:"pattern"`
    Age     string `json:"age"`
    Data    string `json:"data"`
}

  • Related