Search code examples
c#.netrabbitmqrebus

Error when using Rebus with RabbitMQ exclusive queues


I'm getting the following exception when trying to respond to a RabbitMQ exclusive queue using Rebus.

-       e   {"Queue 'xxxx-xxxx' does not exist"}    Rebus.Exceptions.RebusApplicationException

+       InnerException  {"The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=405, text=\"RESOURCE_LOCKED - cannot obtain exclusive access to locked queue 'xxxx-xxxx' in vhost '/'. It could be originally declared on another connection or the exclusive property value does not match that of the original d...\", classId=50, methodId=10, cause="} System.Exception {RabbitMQ.Client.Exceptions.OperationInterruptedException}

The client declares the queue as exclusive and is able to successfully send the message to the server. The server processes the message but throws the exception when sending the response.

I can see in the Rebus source code (Rebus.RabbitMq.RabbitMqTransport.cs) that it attempts a model.QueueDeclarePassive(queueName) which throws the above exception.

I found the following statement Here

RabbitMQ extends the exclusivity to queue.declare (including passive declare), queue.bind, queue.unbind, queue.purge, queue.delete, basic.consume, and basic.get

Modifying the Rebus source to simply return true from the CheckQueueExistence method allows the response message to be sent. So my question is, is this an issue in Rebus with the use of the passive declare on an exclusive queue, is RabbitMQ blocking the call, or is there a fundamental concept I'm missing?


Solution

  • The reason Rebus does the model.QueueDeclarePassive(queueName) thing, is because it tries to help you by verifying the existence of the destination queue before sending to it.

    This is to avoid the situation where a sender goes

    using var bus = Configure.With(...)
        .(...)
        .Routing(r => r.TypeBased().Map<string>("does-not-exist"))
        .Start();
    
    await bus.Send("I'M LOST 😱");
    

    and the message is lost.

    The problem here is that RabbitMQ still uses a routing key to match the sent message to a binding pointing towards a queue, and if no matching binding exists (even when using the DIRECT exchange type) the message is simply routed to 0 queues, and thus it is lost.

    If you submit a PR that makes it configurable whether to check that destination queues exist, then I'd be happy to (help you get it right and) accept it.