Avoiding repeated delivery of browsed messages
By using certain open options and get-message options, we can mark messages as having been browsed so that they are not retrieved again by the current or other cooperating applications. Messages can be unmarked explicitly or automatically to make them available again for browsing.
If you browse messages on a queue, you might retrieve them in a different order to the order in which you would retrieve them if you got them destructively. In particular, we can browse the same message multiple times, which is not possible if it is removed from the queue. To avoid this we can mark messages as they are browsed, and avoid retrieving marked messages. This is sometimes referred to as browse with mark. To mark browsed messages, use the get message option MQGMO_MARK_BROWSE_HANDLE, and to retrieve only messages that are not marked, use MQGMO_UNMARKED_BROWSE_MSG. If we use the combination of options MQGMO_BROWSE_FIRST, MQGMO_UNMARKED_BROWSE_MSG, and MQGMO_MARK_BROWSE_HANDLE, and issue repeated MQGETs, we will retrieve each message on the queue in turn. This prevents repeated delivery of messages even though MQGMO_BROWSE_FIRST is used to ensure that messages are not skipped. This combination of options can be represented by the single constant MQGMO_BROWSE_HANDLE. When there are no messages on the queue that have not been browsed, MQRC_NO_MSG_AVAILABLE is returned.
If multiple applications are browsing the same queue, they can open the queue with the options MQOO_CO_OP and MQOO_BROWSE. The object handle returned by each MQOPEN is considered to be part of a cooperating group. Any message returned by an MQGET call specifying the option MQGMO_MARK_BROWSE_CO_OP is considered to be marked for this cooperating set of handles.
If a message has been marked for some time, it can be automatically unmarked by the queue manager and made available for browsing again. The queue manager attribute MsgMarkBrowseInterval gives the time in milliseconds for which a message is to remain marked for the cooperating set of handles. A MsgMarkBrowseInterval of -1 means that messages are never automatically unmarked.
When the single process or set of cooperative processes marking messages stop, any marked messages become unmarked.
Examples of cooperative browsing
We might run multiple copies of a dispatcher application to browse messages on a queue and initiate a consumer based on the content of each message. In each dispatcher, open the queue with MQOO_CO_OP. This indicates that the dispatchers are cooperating and will be aware of each other's marked messages. Each dispatcher then makes repeated MQGET calls, specifying the options MQGMO_BROWSE_FIRST, MQGMO_UNMARKED_BROWSE_MSG, and MQGMO_MARK_BROWSE_CO_OP (we can use the single constant MQGMO_BROWSE_CO_OP to represent this combination of options). Each dispatcher application then retrieves only those messages that have not already been marked by other cooperating dispatchers. The dispatcher initializes a consumer and passes the MsgToken returned by the MQGET to the consumer, which destructively gets the message from the queue. If the consumer backs out the MQGET of the message, then the message is available for one of the browsers to re-dispatch, because it is no longer marked. If the consumer does not do an MQGET on the message, then after the MsgMarkBrowseInterval has passed, the queue manager unmarks the message for the cooperating set of handles, and it can be re-dispatched.
Rather than multiple copies of the same dispatcher application, you might have a number of different dispatcher applications browsing the queue, each suitable for processing a subset of the messages on the queue. In each dispatcher, open the queue with MQOO_CO_OP. This indicates that the dispatchers are cooperating and will be aware of each other's marked messages.
- If the order of message processing for a single dispatcher is important, each dispatcher makes repeated MQGET calls, specifying the options MQGMO_BROWSE_FIRST, MQGMO_UNMARKED_BROWSE_MSG, and MQGMO_MARK_BROWSE_HANDLE (or MQGMO_BROWSE_HANDLE). If the browsed message is suitable for this dispatcher to process, it then makes an MQGET call specifying MQMO_MATCH_MSG_TOKEN, MQGMO_MARK_BROWSE_CO_OP, and the MsgToken returned by the previous MQGET call. If the call succeeds, the dispatcher initializes the consumer, passing the MsgToken to it.
- If the order of message processing is not important and the dispatcher is expected to process most of the messages it encounters, use the options MQGMO_BROWSE_FIRST, MQGMO_UNMARKED_BROWSE_MSG, and MQGMO_MARK_BROWSE_CO_OP (or MQGMO_BROWSE_CO_OP). If the dispatcher browses a message it cannot process, it unmarks the message by calling MQGET with the option MQMO_MATCH_MSG_TOKEN, MQGMO_UNMARK_BROWSE_CO_OP, and the MsgToken returned previously.
Parent topic: Browsing messages on a queue