Azure / amqpnetlite

AMQP 1.0 .NET Library
Apache License 2.0
401 stars 143 forks source link

How to create a non-durable and a durable queue correctly? #469

Closed PassionateDeveloper86 closed 3 years ago

PassionateDeveloper86 commented 3 years ago

I have a application in which I want to have 1 durable and 1 non-durable queue in Active MQ Artemis. For connecting to this message bus I use amqpnetlite.

        var source = new Source()
        {
        };

        if (durable)
        {
            source.Address = amqpAddressConverter.GetSubscriberAddress(address, useLoadBalancing);
            source.Durable = 1;
            source.ExpiryPolicy = new Symbol("never");
            source.DistributionMode = new Symbol("copy");
        }
        else
        {
            source.Address = amqpAddressConverter.GetSubscriberAddress(address);
            source.Durable = 0;
        }

        var receiverLink = new ReceiverLink(session, linkName, source, null);

So this is my receiver link. As shown I set the Durable uint of the Source which will given into the ReceiverLink.

Because as I saw in the Active MQ Artemis documentation, that the Durable is a boolean but within the amqpnetlite library it is an uint my understanding is that everything over 0 should be true and 0 should be false.

At first the behaviour was very strange: Even when the Aretemis Web interface was shown a queue as durable it would be deleted as soon as no consumer would be connected.

I found this: https://stackoverflow.com/questions/66360625/activemq-artemis-queue-deleted-after-shutdown-of-consuming-client which describes that even durable queues get deleted because of the default behaviour.

So I manipulated the broker.xml and set AUTO-DELETE-QUEUE to false.

Since then the behaviour completly switched: Both (durable = 1 and durable = 0) queues are being still there after the connection disconnected.

So how to create a durable and a non-durable connection correctly?

xinchen10 commented 3 years ago

The durable field is defined as follows in the spec:

<type name="terminus-durability" class="restricted" source="uint">
  <choice name="none" value="0"/>
  <choice name="configuration" value="1"/>
  <choice name="unsettled-state" value="2"/>
</type>

Your settings look fine but I don't know how Active MQ Artemis was handling that.

PassionateDeveloper86 commented 3 years ago

Wow, a fast comment from the main contributer himself :) Thank you Xin.

I work for a mdisze company and where usind Microsoft.Azure.AMqp as well in which you where the main contributor for years, we switchted to this lib a few days ago because of the very good documentation here. (Just a side question: Is this the (in)official successor for the other lib?)

So back to the main question:

Any idea what to do now? I tested a lot but can't get any further. Would you like to debug it with me maybe?

PassionateDeveloper86 commented 3 years ago

After finding out that ActiveMQ seems to have a lot of problems with AMQP 1.0 and durable and non durable subscribers I switched to evaluate RabbitMQ and AMQP 1.0.

Havret commented 3 years ago

@PassionateDeveloper86 Do you mean ActiveMQ Classic or Artemis? The latter has full support of AMQP 1.0, you just need to understand how Artemis Address Model works.

PassionateDeveloper86 commented 3 years ago

@Havret Hey, I use Artemis with AMQP 1.0. Basicly what I found out is, that Artemis seems to ignore the Durable flag on a source. I tried the same code with RabbitMQ which works perfectly, NonDurable Queues are source.Durable = 0, Durable Queues are source.Durable = 1 or 2. Artemis displays all 3 values (0, 1, 2) as durable = true within the attributes.

I think it has something to do with the type of creation of the queue. I found this: "Queues which are auto-created are durable, non-temporary, and non-transient. " Here: https://activemq.apache.org/components/artemis/documentation/2.0.0/address-model.html

So amqpnetlite doesn't seem able to create queues, it just sends the messages and let Artemis do the work. In a dotnet RabbitMQ client I tested within RabbitMQ there are Methods like CreateQueue, which I miss here. A hard indicator that amqpnetlite isn't creating any queues is that when I turn "Auto-create-queue" off in the broker.xml I cant receive any message, it just throws an error.

So at the moment I am still not able to create non durable queues.

Sadly @xinchen10 never replyed to my last question =/

xinchen10 commented 3 years ago

It seems that Artemis doesn't consider source.durable and source.expiry-policy settings for auto-created queues. It might be better to ask this question to the Artemis community to get a quicker answer.

For the durable queue, can you pre-config it in broker config file?

A workaround to get a non-durable queue is to use dynamic/temporary queue.

            Source source = new Source() { Dynamic = true };
            string queueName;
            var link = new ReceiverLink(session, "receiver", source, (link, attach) => queueName = ((Source)attach.Source).Address);

You will not be able to set the queue name but you can still get it in the OnAttached callback.