I'm using ServerRMQ strategy to build microservice in the NestJS application.
I've set noAck field to false in the server options:
const app = await NestFactory.createMicroservice(ApplicationModule, {
strategy: new ServerRMQ({
urls: [RABBITMQ_URI],
queue: EXAMPLE_QUEUE_NAME,
noAck: false,
queueOptions: {durable: false},
}),
});
await app.listenAsync();
When an error occurs during event handling I'm calling channel.nack method to send not acknowledge message to RMQ. After that RMQ should resend the message:
@EventPattern(ExampleMessagePattern.EVENT)
handleExampleEvent(
@Payload() {meta, payload}: IExampleEventData,
@Ctx() context: RmqContext,
) {
try{
... // Performing some actions
} catch(err) {
const message = context.getMesssage();
const channel = context.getChannelRef();
channel.nack(message, false, true);
// or: context.args[1].nack(context.args[0], false, true);
}
}
ER: application creates a consumer with Acknowledgement required feature enabled, and nack method could be successfully called on channel object to perform a retry mechanism when an error occurred.
AR: a consumer is created without acknowledgment feature; channel.nack method call causes an error on RMQ side and service disconnected from the RMQ server.
Error from RabbitMQ stdout:
Error: Channel closed by server: 406 (PRECONDITION-FAILED) with message "PRECONDITION_FAILED - unknown delivery tag 1
I have an assumption that noAck field does not enable acknowledgement feature. To check this I've run a python script using pika library and created a consumer with auto_ack field set to false:
#!/usr/bin/env python
import pika
credentials = pika.PlainCredentials('rabbit', 'rabbit')
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost', credentials=credentials))
channel = connection.channel()
channel.queue_declare(queue='example')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(
queue='example', on_message_callback=callback, auto_ack=False)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
This script created a consumer that has ack feature enabled:
On the screenshot, you could see consumers list in RabbitMQ Management UI. The first one is the python script consumer and is has Ack required set to true. The second one is the NestJS ServerRMQ consumer with noAck set to false (but ack feature does not enable).
I've got the same result when I tried to set noAck to true (which is the default behavior in ServerRMQ).
Does anyone has faced that kind of problem before? Is it related to NestJS ServerRMQ implementation, or I've missed something?
