So far we’ve covered:
– Connecting to a queue manager
–Â Setting a custom client ID
– Joining a shared subscription
The next feature to talk about is how to make subscriptions durable so messages are stored up for clients if they temporarily disconnect.
To create durable subscriptions MQ Light uses the concept of a destination time-to-live. This value specifies the time after which an MQ subscription and its destination (the queue its messages are stored on) will be removed.Â After the last client disconnects from the subscription the time starts counting down. If a client re-joins the subscription before the time-to-live value is exceeded, then the timer is reset and the subscription continues to be used. If no clients join the subscription before the time-to-live value is exceeded, the queue manager deletes the subscription along with any messages that were being stored for it.
Setting a time-to-live value > 0 can be useful as it removes some of the administrative overhead of manually clearing up subscriptions that are no longer being used. However, setting it to a value that is too low could result in the subscription being removed if there is a prolonged outage where clients cannot connect to the queue manager.
AMQP channels don’t support setting an unlimited expiry time for MQ Light subscriptions. While it is possible to create subscriptions that have a very long time-to-live, it isn’t possible to create subscriptions to exist forever.
If you wish to create subscriptions that never expire you can do so by creating an MQ administered subscription and having MQ Light clients join and leave the subscription.Â This can also help to ensure that any messages published to a topic before the first subscribers have connected,Â aren’t lost completely. Read my previous article on joining MQ Light clients to administered subscriptions.
Related AMQP Fields
To provide the expiry capabilities described above MQ Light uses 2 features of AMQP 1.0:
- Source Timeout
- Source Expiry Policy
The source timeout is used to specify the time in seconds that the subscription will expire.
The source expiry policy is used to determine what causes the expiry timer to begin. MQ AMQP channels only support an expiry policy of link-detach, which means the timer starts as soon as the last link detaches from the subscription.
Changes to the Previous Code
In the previous article we used the ReceiverLink() constructor that takes 3 arguments: the session; the link name; and the link address.
To specify our own source timeout and expiry policy we must use the ReceiverLink() constructor that takes 4 arguments:
- the session
- the link name
- the source definition
- a callback to inform us when the linkÂ has been attached.
By passing in our own source definition we can set a timeout value and set the expiry policy to link-detach.
Much of the previous code for receiving messages can be kept the same. Before creating a ReceiverLink we must first create a Source object:
Source source = new Source();
Then we need to set the link address to use, becauseÂ we’re no longer passing the address directly to the ReceiverLink:
source.Address = "share:myshare:public";
Now we must set the expiry policy to link-detach:
source.ExpiryPolicy = new Symbol("link-detach");
Finally we need to configure the timeout we would like. In the case of MQ this is a time in seconds. For a 5 minute expiry time we’ll set the timeout to 300 seconds:
source.Timeout = 300;
Having created a Source object we now need to change the ReceiverLink() constructor to the following:
receiver = new ReceiverLink(session, "share:myshare:public", source, null);
I’ve set the 4th argument – the callback to tell us that we have subscribed successfully – to null to indicate that I don’t want a callback. In production applications you will probably want to use a callback to ensure the subscription has been made successfully.
Testing the Code
When you run your new receiver code you can check that the timeout value has been set correctly on the MQ subscription by using the DISPLAY SUB command in runmqsc:
DISPLAY SUB(':share:myshare:public')Â EXPIRY AMQ8096: IBM MQ subscription inquired. SUBID(414D5120514D3420202020202020202062247B5A23107D09) SUB(:share:myshare:public) EXPIRY(3000)
Remember that MQ uses tenths of a second for expiry values so the EXPIRY attribute will be set to 3000, not 300.
Now if you terminate your application the subscription will continue to exist for 5 minutes. If you don’t resubscribe in that time the subscription will be removed from the queue manager along with any messages that were published to it.