I am trying to use a Controller with MessagePatterns in NestJs to handle messages on some MQTT topics. I am also using an NX monorepo. Everything works fine when I run:
yarn nx serve api
I am working on a deployment strategy, and when I compile my project using:
yarn nx run-many --t=build --configuration=production
Everything is compiling fine.
The issue comes in when I try to run the compiled project using
node ./dist/apps/api/main.js
This causes the following error-message
/home/user/Desktop/project/node_modules/mqtt/lib/client.js:701
const resubscribe = obj.resubscribe
^
TypeError: Cannot read properties of undefined (reading 'resubscribe')
at MqttClient.subscribe (/home/user/Desktop/project/node_modules/mqtt/lib/client.js:701:27)
at /home/user/Desktop/project/node_modules/@nestjs/microservices/server/server-mqtt.js:40:24
at Array.forEach (<anonymous>)
at ServerMqtt.bindEvents (/home/user/Desktop/project/node_modules/@nestjs/microservices/server/server-mqtt.js:38:28)
at ServerMqtt.start (/home/user/Desktop/project/node_modules/@nestjs/microservices/server/server-mqtt.js:32:14)
at ServerMqtt.listen (/home/user/Desktop/project/node_modules/@nestjs/microservices/server/server-mqtt.js:24:18)
at /home/user/Desktop/project/node_modules/@nestjs/microservices/nest-microservice.js:107:25
at new Promise (<anonymous>)
at NestMicroservice.listen (/home/user/Desktop/project/node_modules/@nestjs/microservices/nest-microservice.js:106:16)
Here is a snippet from my main.ts file:
const mqtt_app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.MQTT,
options: {
url: process.env.MQTT_URL,
username: process.env.MQTT_USERNAME,
password: process.env.MQTT_PASSWORD,
},
});
mqtt_app.listen();
If I don't call mqtt_app.listen();
, I don't have an issue, but that also means that nothing related to MQTT will work.
My mqtt.controller file:
import { Controller } from '@nestjs/common';
import { MessagePattern, Payload } from '@nestjs/microservices';
@Controller()
export class MqttController {
@MessagePattern(process.env.MQTT_TOPIC_1)
async mqtt_a(@Payload() data) {
console.log(`Received ${data} on ${process.env.MQTT_TOPIC_1}`);
return `Received ${data} on ${process.env.MQTT_TOPIC_1}}`
};
@MessagePattern(process.env.MQTT_TOPIC_2)
async mqtt_b(@Payload() data) {
console.log(`Received ${data} on ${process.env.MQTT_TOPIC_2}`);
return `Received ${data} on ${process.env.MQTT_TOPIC_2}}`
}
}
If I comment out the two @MmessagePattern()'s and functions mqtt_a and mqtt_b, everything seems to work fine. I suspect that when I run this using NodeJS directly, it tries to 'subscribe' to a topic before the microservice is running, or something simillar?
Maybe I am missing something very obvious, but I am out of ideas and any help regarding this will be greatly appreciated!
The issue was using .env for the messagepatterns
@MessagePattern(process.env.MQTT_TOPIC_2)
Fixed by rather doing
@MessagePattern('topic')
This only seems to be an issue when running the compiled code using NodeJS though, and for some reason using process.env.* works fine when running the project using NX / NestJS directly.