Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoAck not working as expected? #243

Closed
msnelling opened this issue Jul 20, 2017 · 5 comments
Closed

NoAck not working as expected? #243

msnelling opened this issue Jul 20, 2017 · 5 comments
Labels

Comments

@msnelling
Copy link
Contributor

Hi,
I am using a subscriber with the following configuration

                cfg.WithQueue(
                        q => q
                            .WithName("tmq")
                            .WithDurability()
                    )
                    .WithExchange(
                        e => e
                            .WithName("tmx")
                            .WithType(ExchangeType.Fanout)
                            .WithDurability()
                    )
                    .WithSubscriberId("")
                    .WithRoutingKey("")
                    .WithNoAck());

Posting a message to the queue using the RabbitMQ management website and it is throwing an exception on deserialization (this is expected in my case).

I'm using custom error handling to avoid faulty messages being published to the error exchange. I would simply like them to remain on the queue unacknowledged.

However, what I'm seeing is the message being Ack'd anyway and disappearing off the queue.

This is the OnSubscriberExceptionAsync function code in the custom error strategy.

        public override async Task OnSubscriberExceptionAsync(
            IRawConsumer consumer, 
            SubscriptionConfiguration config,
            BasicDeliverEventArgs args, 
            Exception exception)
        {
            if (!config.NoAck)
            {
                consumer.Model.BasicAck(args.DeliveryTag, false);
                consumer.AcknowledgedTags.Add(args.DeliveryTag);
            }

            Log.LogError("Exception thrown in subscriber: ", exception);
            await Task.FromResult(0);
        }
    }

In the debugger I can see that my custom strategy isn't performing the Ack.

@pardahlman
Copy link
Owner

Hello @msnelling - thanks for reporting this!

I believe that you might have misunderstood how NoAck works. It is a feature that, when active, tells the broker/server that no acknowledgement will be sent, but rather the message is automatically ack'ed. The property is poorly named, which is why it is renamed to AutoAck in an upcoming version of RabbitMQ.Client (see rabbitmq/rabbitmq-dotnet-client#297).

Hope this helps!

@pardahlman
Copy link
Owner

On a different note: when you say "I would simply like them to remain on the queue unacknowledged" do you mean that you want the client in which the exception occurred to keep the message unack'ed? If that's the case, then I would say it is a bit unconventional approach, as the message will be "processed" by the client forever. The only way to get the client to "release" the message would be to close the consumer's channel (by closing the channel, connection or simply restart the service).

Perhaps you've already seen this, but there is a requeue with delay feature in RawRabbit. Not sure if it is close to what you want to do.

@msnelling
Copy link
Contributor Author

Yes I can see how that sounds, the reason for not immediately Ack'ing the message is so that if for some reason the client crashes, or was running an older version of our protocol by mistake, the message isn't lost and is waiting in the queue for when the client restarts. We do Ack the message, but only after we have successfully processed it.
Ordering of our messages is important too, we wouldn't want a message to be requeued and then be processed out of order.

@pardahlman
Copy link
Owner

Perfect! Well, I think you will get the desired behavior by removing the NoAck from the subscriber configuration and in your custom error strategy simply do this

            if (!config.NoAck)
            {
                // don't ack here, but put in in the list of acknowledged tags;
                consumer.AcknowledgedTags.Add(args.DeliveryTag);
            }

@msnelling
Copy link
Contributor Author

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants