Nest: [MQTT Microservices] Wildcard support

Created on 13 Sep 2019  路  3Comments  路  Source: nestjs/nest

Bug Report

Current behavior

When @EventPattern is supplied with a wildcard, e.g. sensor/+/status, a There is no matching event handler defined in the remote service error is logged (similar: #2236). However, when supplying the full topic string, e.g. sensor/1/status, the event is caught as normal.

Input Code

@EventPattern('sensor/+/status')
async handleStatus(data: Record<string, string>) {
    console.log(data);
}

Expected behavior

Receiving a message with topic sensor/1/status should be handled by both handlers with pattern sensor/+/status and handlers with pattern sensor/#.

Possible Solution

When receiving an event, check for wildcards in the registered patterns, such as + and #, before matching to handlers. It might have similar solution to #2447

Environment


Nest version: 6.6.7

For Tooling issues:
- Node version: 10.16.0
- Platform:  Windows

Others:

needs triage

Most helpful comment

For anyone who are still looking for a solution, please use this custom strategy:

import { MessageHandler } from '@nestjs/microservices/interfaces';
import { ServerMqtt } from '@nestjs/microservices/server';

import {
    MQTT_WILDCARD_ALL,
    MQTT_WILDCARD_SINGLE,
} from './constants';

import { matches } from './mqtt-pattern';

export class CustomServerMqtt extends ServerMqtt {

    public getHandlerByPattern(pattern: string): MessageHandler | null {

        if (this.messageHandlers.has(pattern)) {
            return this.messageHandlers.get(pattern);
        }

        for (const [key, value] of this.messageHandlers) {
            if ((key.indexOf(MQTT_WILDCARD_SINGLE) !== -1
                || key.indexOf(MQTT_WILDCARD_ALL) !== -1)
                && matches(key, pattern)) {
                return value;
            }
        }

        return null;
    }

}

and bootstrap it as ussual

export async function bootstrapMicroservice() {
    const microservice = await NestFactory.createMicroservice(ApplicationModule, {
        strategy: new CustomServerMqtt({
            url: `mqtt://localhost:1881`,
        }),
    });

    await microservice.listenAsync();
}

All 3 comments

For anyone who are still looking for a solution, please use this custom strategy:

import { MessageHandler } from '@nestjs/microservices/interfaces';
import { ServerMqtt } from '@nestjs/microservices/server';

import {
    MQTT_WILDCARD_ALL,
    MQTT_WILDCARD_SINGLE,
} from './constants';

import { matches } from './mqtt-pattern';

export class CustomServerMqtt extends ServerMqtt {

    public getHandlerByPattern(pattern: string): MessageHandler | null {

        if (this.messageHandlers.has(pattern)) {
            return this.messageHandlers.get(pattern);
        }

        for (const [key, value] of this.messageHandlers) {
            if ((key.indexOf(MQTT_WILDCARD_SINGLE) !== -1
                || key.indexOf(MQTT_WILDCARD_ALL) !== -1)
                && matches(key, pattern)) {
                return value;
            }
        }

        return null;
    }

}

and bootstrap it as ussual

export async function bootstrapMicroservice() {
    const microservice = await NestFactory.createMicroservice(ApplicationModule, {
        strategy: new CustomServerMqtt({
            url: `mqtt://localhost:1881`,
        }),
    });

    await microservice.listenAsync();
}

I believe this can be closed no?

Correct @wesselvdv. This feature is already available in the framework.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cojack picture cojack  路  3Comments

anyx picture anyx  路  3Comments

rlesniak picture rlesniak  路  3Comments

menme95 picture menme95  路  3Comments

marshall007 picture marshall007  路  3Comments