Manual Acknowledgment
60East generally recommends that applications use an ack()
method
to acknowledge messages during normal processing. This approach functions
correctly when used within a message handler, supports batching as
explained elsewhere in this chapter, and is generally both easier to
code and more efficient.
However, in some situations, you may need to manually acknowledge messages in the queue. This is most common when an application needs to operate on all messages with certain characteristics, rather than acknowledging individual messages. For example, an application that is doing updates to an order may want to cancel an order by both publishing a cancellation and immediately expiring all other messages in the queue for that order. With manual acknowledgment, that application can use a filter to remove all previous updates for that order, then publish the cancellation.
To manually acknowledge processed messages and remove the messages from
the queue, applications use the sow_delete
command. To remove
specific messages from the queue, provide the bookmarks of those
messages. To remove messages that match a given filter, provide
the filter. Notice that AMPS only supports
using a bookmark with sow_delete
when removing messages from a
queue, not when removing records from a SOW.
For example, given a Message
object to acknowledge and a client, the
code below acknowledges the message.
# Provided as a demonstration for cases
# where the message itself isn't available.
#
# Where the message is available, this method
# is typically less efficient than
# simply calling message.ack()
def acknowledgeSingle(client,message):
acknowledge = Command("sow_delete")
acknowledge.set_topic(message.get_topic()).set_bookmark(message.get_bookmark())
client.execute_async(acknowledge,None)
In the example above, the program creates a sow_delete
command,
specifies the topic and the bookmark, and then sends the command to the server.
Since the program does not need or expect a response from AMPS, this function
provides None
as the message handler.
While this method works, creating and sending an acknowledgment for
each individual message can be inefficient if your application is
processing a large volume of messages. Rather than acknowledging each
message individually, your application can build a comma-delimited list
of bookmarks from the processed messages and acknowledge all of the
messages at the same time. In this case, it's important to be sure that
the number of messages you wait for is less than the maximum backlog --
the number of messages your client can have unacknowledged at a given
time. Notice that both automatic acknowledgment and the helper method
on the Message
object take the maximum backlog into account.
When constructing a command to acknowledge queue messages, AMPS allows an
application to specify a filter rather than a set of bookmarks. AMPS interprets
this as the client requesting acknowledgment of all messages that match the
filter. (This may include messages that the client has not received, subject
to the Leasing
model for the queue.)
As a more typical example of manual acknowledgment, the code below expires
all messages for a given id
that have a status other than cancel
. An
application might do this to halt processing of an order that it is about
to cancel.
def removePending(client, orderId):
acknowledge = Command("sow_delete")
acknowledge.set_topic(message.get_topic()) \
.set_filter("/id = '%s' and /status != 'cancel'" % orderId).set_options("expire")
client.execute_async(acknowledge,None)
In the example above, the program specifies a topic and a filter to
use to find the messages that should be removed. In this case, the program
also provides the expire
option to indicate that the messages have been
removed from the queue rather than successfully processed (of course, whether
this is the correct behavior for a canceled order depends on the expected
message flow for your application).
Notice that, as described in Understanding Threading, this method
of acknowledging a message should not be used from a message handler unless
the sow_delete
is sent from a different client than the client that
called the message handler. Instead, 60East recommends using the ack()
function from within a message handler.