AlariCode / nestjs-rmq

A custom library for NestJS microservice. It allows you to use RabbitMQ or AMQP.
https://purpleschool.ru
MIT License
285 stars 38 forks source link

How do you ack messages? #19

Closed thekvn closed 3 years ago

thekvn commented 3 years ago

Hello, great library, I couldn't find it in the docs, how do you acknowledge messages in handlers with this library?

AlariCode commented 3 years ago

Hello! Thanks for using it. Library acknowledge messages automatically when RMQRoute where message is processed returns, so you don't need to do it manually.

thekvn commented 3 years ago

We want to handle ack manually

AlariCode commented 3 years ago

Can you describe a usecase for manual ack?

thekvn commented 3 years ago

We want to we explicit about whether we ack a message or not. This is so we can ensure messages are re-queued and re-delivered for messages we failed to process.

For example, we might have a queue for performing email deliveries, we would only want to ack when email delivery was successful, or if an email delivery was unsuccessful after N redelivery attempts, in this case we want to use nAck

AlariCode commented 3 years ago

@thekvn, message will be re-queued and re-delivered if your RMQRoute will throw an Exception. In you case you should return from route only if delivery is successful, and if not, throw an exception (or add additional retries before it). This way your message will return to queue. Will it solve your problem? The mail goal of this library is to provide simple pattern for RPC. Manual message ack will lead to additional complexity.

mjarmoc commented 3 years ago

@AlariCode from what I see, throwing in EventRoute either return an error for send or ack message for notify. I assume, @thekvn case is about notify.

https://github.com/AlariCode/nestjs-rmq/blob/83b04d1f46472271b1ac18d792e3f6d3f197dca0/lib/decorators/rmq-controller.decorator.ts#L43-L49

I also think that @thekvn functionality is a need and got 2 ideas:

  1. @Message decorator, for extracting message in RMQRoute and manually acknowledge it.
  2. I don't believe that throwing should always requeue. Maybe throwing a specific Error Class instance? Like throw new NoAckError()
AlariCode commented 3 years ago

@mjarmoc

  1. Good idea. Can do that later or PR will be appreciated.
  2. Yes, but it will be a breaking change. May be additional RMQRoute option will solve this?
AlariCode commented 3 years ago

@thekvn, @mjarmoc thanks for your patience! I added two new features to nestjs-rmq 1.13.0.

  1. Now you can access Message with @RMQMessage decorator, that not only contains contents, but all its metadata.
import { RMQController, RMQRoute, Validate, RMQMessage, ExtendedMessage } from 'nestjs-rmq';

@RMQRoute('my.rpc')
myMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {
    // ...
}
  1. RMQService now has public ack method
    this.rmqService.ack(msg);
  2. You can prevent message from acknowledgement with new @RMQRoute option manualAck.
    
    @RMQRoute('my.rpc', { manualAck: true })
    myMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {

}


So if you want to manually ack message:
```typescript
@RMQRoute('my.rpc', { manualAck: true })
myMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {
        // Any logic goes here
        this.rmqService.ack(msg);
    // Any logic goes here
}

Will this solve your case? @mjarmoc thx for decorator idea!

AlariCode commented 3 years ago

One small addition before closing issue. In 1.14.0 I added ExtendedMessage so you can use additional debug method. Now usage is

myMethod(data: myClass, @RMQMessage msg: ExtendedMessage): number {