nestjs/nest

Alternating success/error with RabbitMQ: There is no equivalent message pattern defined in the remote service.

Closed this issue ยท 20 comments

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

When I used RabbitMQ with microservices, I get an alternating response/error "There is no equivalent message pattern defined in the remote service.". One message will work, the next will not, and repeat. It always alternates, it is not randomly failing, it reliably fails and works, fails and works.

This does not happen with the other transports I've tried, NATS/REDIS

Expected behavior

This doesn't happen.

Minimal reproduction of the problem with instructions

One nest app is a graphql server, followed by other nest apps all connected via microservices messaging with basic rabbitmq:3 docker container.
In graphql gateway I am using ClientProxyFactory to create a client with RMQ transport, to connect to the other services in the resolvers. Normally works but wanted to try RabbitMQ.
Repo that doesn't reproduce (sadly) patricknazar/nestjs-rabbitmq-problem

What is the motivation / use case for changing the behavior?

It should work

Environment


Nest version: 5.4.0

 
For Tooling issues:
- Node version: 8
- Platform:  Linux

Others:

Yarn

We need a way to somehow reproduce your issue. Could you share a minimal reproduction repository?

Sure i'll get onto that

Sadly my reproduction repo didn't have the problem... sigh. I can't even begin to figure out why this is happening.

Can you maybe post the reproduction here, I've got the same problem at the moment

This is extremely strange. I tried now my controller call with your codebase, and it works too. I also add a custom queue.

Yeah, I also tried with custom queue on both my other repo and this one, made no difference :/

Ok I found a difference.

When I create a sub module and add the microservice controller to the submodule, I get the error " There is no equivalent message pattern defined in the remote service.". When I add the microservice controller directly to the application definition, it works.

Adding Microservice Controller to submodule, does this need a prefix for a cmd pattern?

Sorry this is the first i'm working with the microservice functionality, so maybe i missed something in the tutorial

Ok I found a difference.

When I create a sub module and add the microservice controller to the submodule, I get the error " There is no equivalent message pattern defined in the remote service.". When I add the microservice controller directly to the application definition, it works.

Adding Microservice Controller to submodule, does this need a prefix for a cmd pattern?

Sorry this is the first i'm working with the microservice functionality, so maybe i missed something in the tutorial

@kamilmysliwiec do you have a solution for this problem, or is this a bug?

Add a microservice controller directly to the definition.ts and use the cmd patter => it works

Create a sub module, add this sub module to the definition.ts and add the microservice controller to the sub module => it don't work

I can't actually reproduce that, I've moved it to a submodule and it still works :/

@kamilmysliwiec @andreastoermer
Ok I've been able to reproduce the bug. It happens where there is more than one microservice. I've added another one "microservice2" and changed the message handler slightly. The issue now happens. Repo updated patricknazar/nestjs-rabbitmq-problem

have you tried to add a custom queue for each microservice?

@kamilmysliwiec @andreastoermer
Ok I've been able to reproduce the bug. It happens where there is more than one microservice. I've added another one "microservice2" and changed the message handler slightly. The issue now happens. Repo updated patricknazar/nestjs-rabbitmq-problem

I've got the same problem with two connected microservices (and different queues)

Even if i disable the "old" microservice and only create a call with a different cmd to the new, i get the error message, very strange ...

I found the problem in my code (the pattern object in my second call was wrong), and now everything works

Just to recap, this repo reproduces the issue, am I right? https://github.com/patricknazar/nestjs-rabbitmq-problem

@kamilmysliwiec That's correct

Hi @patricknazar
From my investigation, RabbitMQ queue is routing by round-robin algorithm.
@nestjs/microservice routed the message pattern until it reached to the service. Message Pattern didn't route by RabbitMQ.
If your microservice is listening to the same queue and didn't implement MessagePattern for all service, then you will get that issue.
So my suggestion, you can group MessagePattern for each queue and listen to services used that queue.
For example:

  • "graphql-gateway" client proxy send to "queue_1" with pattern "getUsers"
  • "microservice" server listen to "queue_1" and subscribe pattern "getUsers"
  • "microservice2" server listen to "queue_2" and subscribe pattern "getSomethingElse"
    That will solve your issue.

BTW, Current @nestjs/miscroservice supports listen with multiple queues (will be multiple connection).

Hi @kamilmysliwiec ,
Can @nestjs/miscroservice support multiple queue for same connection.
For example:
app.connectMicroservice({
transport: Transport.RMQ,
options: {
urls: [amqp://rabbitmq:5672],
queues: [
'queue_1',
'queue_2'
],
queueOptions: {
durable: false,
},
},
});

Thanks for your response. I'll close for now. I'd be grateful for any more comments on the matter.

Hi, this problem happens to me too. I have 2 microservices, first one is configured like this

// main.ts
 app.connectMicroservice({
        transport: Transport.RMQ,
        options: {
            urls: [`amqp://localhost:5672`],
            queue: 'manager_service_queue',
            queueOptions: {
                durable: false,
           }
      }
});

and has controller like this:

@Controller()
export class MyController {

    constructor(
        private ordersService: OrdersService,
        private logger: AppLoggerService){}

    @MessagePattern({cmd: RmqPatterns.ORDER_PAYMENT_REJECTED})
    async orderRejected(paymentStatusDto: PaymentStatusDto) {
        this.ordersService.changeOrderStatus(
            paymentStatusDto.status,
            paymentStatusDto.userId,
            paymentStatusDto.orderId,
            paymentStatusDto.reason,
        );
    }

    @MessagePattern({cmd: RmqPatterns.ORDER_CREATED})
    async orderCreated(newOrder: Order) {
        this.ordersService.notifyNewOrder(newOrder);
    }

    @MessagePattern({cmd: RmqPatterns.ORDER_PAYMENT_APPROVED})
    async orderApproved(paymentStatusDto: PaymentStatusDto) {
        this.ordersService.changeOrderStatus(
            paymentStatusDto.status,
            paymentStatusDto.userId,
            paymentStatusDto.orderId,
            paymentStatusDto.reason,
        );
    }
}

second one has this logic:

// my-service.service.ts
// ...
 @Client({
    transport: Transport.RMQ,
    options: {
      urls: [`amqp://localhost:5672`],
      queue: 'manager_service_queue',
      queueOptions: {durable: false},
    },
  })
  managerQueue: ClientProxy;

  callAnotherService(){
     return this.managerQueue.send({cmd: RmqPatterns.ORDER_CREATED}, order);
  }
// ....

When callAnotherService method is called first time I receive this error:
There is no equivalent message pattern defined in the remote service
Second call seems to be OK, third fails again, fourth work, etc. ๐Ÿ˜„
In other words even calls work and odd calls fail.
Does anyone know why it happens? And perhaps more important thing is what to do with that ๐Ÿค”
Will appreciate any help ๐Ÿ™

lock commented

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.