7. Using Queues

AMPS message queues provide a high-performance way of distributing messages across a set of workers. The AMPS User Guide describes AMPS queues in detail, including the features of AMPS referred to in this chapter. This chapter does not describe AMPS queues in detail, but instead explains how to use the AMPS JavaScript client with AMPS queues.

To publish messages to an AMPS queue, publishers simply publish to any topic that is collected by the queue. There is no difference between publishing to a queue and publishing to any other topic, and a publisher does not need to be aware that the topic will be collected into a queue.

Subscribers must be aware that they are subscribing to a queue, and acknowledge messages from the queue when the message is processed.

Backlog and Smart Pipelining

AMPS queues are designed for high-volume applications that need minimal latency and overhead. One of the features that helps performance is the subscription backlog feature, which allows applications to receive multiple messages at a time. The subscription backlog sets the maximum number of unacknowledged messages that AMPS will provide to the subscription.

When the subscription backlog is larger than 1, AMPS delivers additional messages to a subscriber before the subscriber has acknowledged the first message received. This technique allows subscribers to process messages as fast as possible, without ever having to wait for messages to be delivered. The technique of providing a consistent flow of messages to the application is called smart pipelining.

Subscription Backlog

The AMPS server determines the backlog for each subscription. An application can set the maximum backlog that it is willing to accept with the max_backlog option. Depending on the configuration of the queue (or queues) specified in the subscription, AMPS may assign a smaller backlog to the subscription. If no max_backlog option is specified, AMPS uses a max_backlog of 1 for that subscription.

In general, applications that have a constant flow of messages perform better with a max_backlog setting higher than 1. The reason for this is that, with a backlog greater than 1, the application can always have a message waiting when the previous message is processed. Setting the optimum max_backlog is a matter of understanding the messaging pattern of your application and how quickly your application can process messages.

To request a max_backlog for a subscription, you explicitly set the option on the subscribe command, as shown below:

var command = new amps.Command('subscribe')
                .topic('my-queue')
                .options('max_backlog=10');

Acknowledging Messages

For each message delivered on a subscription, AMPS counts the message against the subscription backlog until the message is explicitly acknowledged. In addition, when a queue specifies at-least-once delivery, AMPS retains the message in the queue until the message expires or until the message has been explicitly acknowledged and removed from the queue. From the point of view of the AMPS server, acknowledgment is implemented as a sow_delete from the queue with the bookmarks of the messages to remove. The AMPS JavaScript client provides several ways to make it easier for applications to create and send the appropriate sow_delete.

Automatic Acknowledgment

The AMPS client allows you to specify that messages should be automatically acknowledged. When this mode is on, AMPS acknowledges the message automatically if the message handler returns without throwing an exception.

AMPS batches acknowledgments created with this method, as described in the following section.

To enable automatic acknowledgment batching, use the Client.autoAck() method.

client.autoAck(true);  // enable AutoAck

Message Convenience Method

The AMPS JavaScript client provides a convenience method, Client.ack(), on delivered messages. When the application is finished with the message, the application simply calls Client.ack() on the message.

For messages that originated from a queue with at-least-once semantics, this adds the bookmark from the message to the batch of messages to acknowledge. For other messages, this method has no effect.

// Add the message to the next acknowledgment batch
client.ack(message);

Manual Acknowledgment

To manually acknowledge processed messages and remove the messages from the queue, applications use the sow_delete command with the bookmarks of the messages to remove. 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.

function acknowledgeSingle(client, message) {
    return client.execute(
        new amps.Command('sow_delete')
            .topic(message.header.topic())
            .bookmark(message.header.bookmark());
    );
}

Example 7.1: Simple queue acknowledgment

In listing Example 7.1 the program creates a sow_delete command, specifies the topic and the bookmark, and then sends the command to the server.

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 convenience method Client.ack() take the maxiumum backlog into account.

Acknowledgment Batching

The AMPS JavaScript client automatically batches acknowledgments when either of the convenience methods is used. Batching acknowledgments reduces the number of round-trips to AMPS, which reduces network traffic and improves overall performance. AMPS sends the batch of acknowledgments when the number of acknowledgments exceeds a specified size, or when the amount of time since the last batch was sent exceeds a specified timeout.

You can set the number of messages to batch and the maximum amount of time between batches:

client.ackBatchSize(10);  // Send batch after 10 messages
client.ackTimeout(1000);  // ... or 1 second

The AMPS JavaScript client is aware of the subscription backlog for a subscription. When AMPS returns the acknowledgment for a subscription that contains queues, AMPS includes information on the subscription backlog for the subscription. If the requested batch size is larger than the subscription backlog, the AMPS JavaScript client adjusts the requested batch size to match the subscription backlog.

Returning a Message to the Queue

A subscriber can also explicitly release a message back to the queue. AMPS returns the message to the queue, and redelivers the message just as though the lease had expired. To do this, the subscriber sends a sow_delete command with the bookmark of the message to release and the cancel option:

client.execute(
    new amps.Command('sow_delete')
        .topic(message.header.topic())
        .bookmark(message.header.bookmark())
        .options('cancel');
);

When using automatic acknowledgments, AMPS will cancel a message if an exception is thrown from the message handler.