6.5.2. Automatically Deleted Queue Example

The following Python code demonstrates the behavior of an auto-delete queue. Auto-delete queues are cleaned up by the broker when an application quits. They are usually used to subscribe to an exchange, and a typical use-case is to create an auto-delete queue to specify in the "reply-to" field of a message, to get a response back.
This demonstration uses an auto-delete queue to publish information to a subscriber. This is not a typical use of auto-delete queue, for reasons that we will discover.
Copy the code below and save it as auto-delete-producer.py. It can be run using a Python interpreter.
Python
import sys
from qpid.messaging import *

connection=Connection("localhost:5672")
connection.open()
try:
  session=connection.session()
  tx=session.sender("test-queue; {create:always, node:{x-declare:{auto-delete:True}}}")
  tx.send("test message!")
  x = raw_input("Press Enter to continue")
  tx.send("test message 2")
except MessagingError, m:
  print m
connection.close()
Restart the broker on the local machine. Whenever the broker is restarted, all non-durable queues are deleted. This allows you to start this test with a clean slate.
Run the command:
qpid-config queues
This lists all the queues on the broker. There will be a dynamically generated queue with a random name with exclusive and auto-del. This is the queue that qpid-config is using to retrieve the list of queues, and will change each time you run the command.
Now start the auto-delete-producer.py program using a Python interpreter:
python auto-delete-producer.py
The program pauses and prompts you to press Enter. Press Enter to continue.
Now run qpid-config queues again to list the queues on the broker. This time you will see the test-queue that our program created. Our program has exited, but the queue has not been deleted because so far no-one has subscribed to it.
Note that there is a difference in the amqp1.0 behaviour. Using amqp0-10 the queue is deleted when not in use only if there have been consumers, using amqp1.0 the queue is deleted when not in use even if there have never been any consumers.
We will now use the drain utility to examine the messages on the queue. The drain utility is part of the C++ and Python client library packages.
When drain runs, it subscribes to the queue, retrieves messages, and then unsubscribes. Run:
drain -c 0 test-queue
The messages from the test-queue will be displayed on the screen. When you run qpid-config queues now, you will see that the test-queue has been deleted. A consumer subscribed to the queue, and then unsubscribed.
Try the process again, and this time use drain to browse the queue, rather than acquire the messages:
drain -c 0 "test-queue;{mode:browse}"
You will observe that the queue is deleted even when it is browsed. Browsing counts as a subscription as much as acquiring.
Now, to see something very interesting, we will subscribe to the queue and then unsubscribe while our program is running.
Copy the following code into a file auto-delete-subscribe.py:
Python
import sys
from qpid.messaging import *

connection=Connection("localhost:5672")
connection.open()
try:
  session=connection.session()
  rx=session.receiver("test-queue")
  print rx.fetch(timeout = 1)
  session.acknowledge()  
except MessagingError,m:
  print m
connection.close()
Now run auto-delete-producer.py. When it pauses, run auto-delete-subscriber.py, then check qpid-config queues. You'll see that the queue has been deleted.
Now press Enter to continue. When the program finishes, use drain to browse the test-queue. It doesn't exist.
The test-queue created by auto-delete-producer.py was deleted when our consumer program subscribed to the queue by creating and attaching a receiver, and then unsubscribed by closing the connection. The second message sent by our message producer was never delivered and no exception was raised.
This is something to be aware of: a sender is a handle to a local router that routes messages to the message broker. The constructor parameter of the sender is a routing key. Our constructor is the name of a queue, but a sender always routes messages to an exchange. When no exchange is specified, the default exchange is used: a nameless direct exchange on the broker. The sender's constructor checks that the routing key it is given refers to a valid target on the message broker, so it checks that there is a "test-queue" on the default exchange. At the time the sender is created this queue exists. After that, the sender's send method routes messages to the default exchange on the broker with a routing key set to "test-queue". Since the target exchange still exists no exception is raised when we send. The message arrives at the default exchange on the broker, where it is discarded because there is no queue subscribed to the exchange that matches the routing key.
To avoid this scenario, you should either use a non-auto-deleting queue for publishing, or you can create and subscribe a receiver alongside the sender. This guarantees that the queue will continue to exist for the lifetime of your sender. To do this in our program, we will create and subscribe a receiver directly after the sender creates the queue. We will also add a second pause where we can check the existence and state of the test-queue. Here's the updated program:
Python
import sys
from qpid.messaging import *

connection=Connection("localhost:5672")
connection.open()
try:
  session=connection.session()
  tx=session.sender("test-queue; {create:always, node:{x-declare:{auto-delete:True}}}")
  rx=session.receiver("test-queue")
  tx.send("test message!")
  x = raw_input("Press Enter to continue")
  tx.send("test message 2")
  x = raw_input("Press Enter to continue")
except MessagingError, m:
  print m
connection.close()
Now start the auto-delete-producer.py program. Run auto-delete-subscriber.py in the first pause. Previously, this would delete the queue, and the second message would go nowhere. This time our producer's own subscription is keeping the queue alive. Press Enter to have auto-delete-producer.py send the second message. Now check the queue using either drain or auto-delete-subscriber.py. This time you'll see that the queue exists and the message has been delivered as expected.