| <?xml version="1.0" encoding="utf-8"?> |
| <!-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| |
| --> |
| |
| <section> |
| <title>LVQ - Last Value Queue</title> |
| |
| <section role="h2" id="LVQ-UnderstandingLVQ"> |
| <title>Understanding LVQ</title> |
| <para> |
| A Last Value Queue is configured with the name of a message header that |
| is used as a key. The queue behaves as a normal FIFO queue with the |
| exception that when a message is enqueued, any other message in the |
| queue with the same value in the key header is removed and discarded. |
| Thus, for any given key value, the queue holds only the most recent |
| message. |
| </para> |
| <para> |
| The following example illustrates the operation of a Last Value Queue. |
| The example shows an empty queue with no consumers and a sequence of |
| produced messages. The numbers represent the key for each message. |
| </para> |
| <programlisting> |
| <empty queue> |
| 1 => |
| 1 |
| 2 => |
| 1 2 |
| 3 => |
| 1 2 3 |
| 4 => |
| 1 2 3 4 |
| 2 => |
| 1 3 4 2 |
| 1 => |
| 3 4 2 1 |
| </programlisting> |
| <para> |
| Note that the first four messages are enqueued normally in FIFO order. |
| The fifth message has key '2' and is also enqueued on the tail of the |
| queue. However the message already in the queue with the same key is |
| discarded. |
| <note> |
| <para> |
| If the set of keys used in the messages in a LVQ is constrained, the |
| number of messages in the queue shall not exceed the number of |
| distinct keys in use. |
| </para> |
| </note> |
| </para> |
| <section role="h3" id="LVQ-UnderstandingLVQ-UseCases"> |
| <title>Common Use-Cases</title> |
| <itemizedlist> |
| <listitem> |
| <para> |
| LVQ with zero or one consuming subscriptions - In this case, if |
| the consumer drops momentarily or is slower than the producer(s), |
| it will only receive current information relative to the message |
| keys. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| LVQ with zero or more browsing subscriptions - A browsing consumer |
| can subscribe to the LVQ and get an immediate dump of all of the |
| "current" messages and track updates thereafter. Any number of |
| independent browsers can subscribe to the same LVQ with the same |
| effect. Since messages are never consumed, they only disappear |
| when replaced with a newer message with the same key or when their |
| TTL expires. |
| </para> |
| </listitem> |
| </itemizedlist> |
| </section> |
| </section> |
| |
| <section role="h2" id="LVQ-Creating"> |
| <title>Creating a Last Value Queue</title> |
| <section role="h3" id="LVQ-Creating-Address"> |
| <title>Using Addressing Syntax</title> |
| <para> |
| A LVQ may be created using directives in the API's address syntax. |
| The important argument is "qpid.last_value_queue_key". The following |
| Python example shows how a producer of stock price updates can create |
| a LVQ to hold the latest stock prices for each ticker symbol. The |
| message header used to hold the ticker symbol is called "ticker". |
| </para> |
| <programlisting> |
| conn = Connection(url) |
| conn.open() |
| sess = conn.session() |
| tx = sess.sender("prices;{create:always, node:{type:queue, x-declare:{arguments:{'qpid.last_value_queue_key':'ticker'}}}}") |
| </programlisting> |
| </section> |
| <section role="h3" id="LVQ-Creating-Tool"> |
| <title>Using qpid-config</title> |
| <para> |
| The same LVQ as shown in the previous example can be created using the |
| qpid-config utility: |
| </para> |
| <programlisting> |
| $ qpid-config add queue prices --lvq-key ticker |
| </programlisting> |
| </section> |
| </section> |
| |
| <section role="h2" id="LVQ-Example"> |
| <title>LVQ Example</title> |
| |
| <section role="h3" id="LVQ-Example-Sender"> |
| <title>LVQ Sender</title> |
| <programlisting> |
| from qpid.messaging import Connection, Message |
| |
| def send(sender, key, message): |
| message.properties["ticker"] = key |
| sender.send(message) |
| |
| conn = Connection("localhost") |
| conn.open() |
| sess = conn.session() |
| tx = sess.sender("prices;{create:always, node:{type:queue,x-declare:{arguments:{'qpid.last_value_queue_key':ticker}}}}") |
| |
| msg = Message("Content") |
| send(tx, "key1", msg); |
| send(tx, "key2", msg); |
| send(tx, "key3", msg); |
| send(tx, "key4", msg); |
| send(tx, "key2", msg); |
| send(tx, "key1", msg); |
| |
| conn.close() |
| </programlisting> |
| </section> |
| |
| <section role="h3" id="LVQ-Example-Receiver"> |
| <title>LVQ Browsing Receiver</title> |
| <programlisting> |
| from qpid.messaging import Connection, Message |
| |
| conn = Connection("localhost") |
| conn.open() |
| sess = conn.session() |
| rx = sess.receiver("prices;{mode:browse}") |
| |
| while True: |
| msg = rx.fetch() |
| sess.acknowledge() |
| print msg |
| </programlisting> |
| </section> |
| </section> |
| |
| <section role="h2" id="LVQ-Deprecated"> |
| <title>Deprecated LVQ Modes</title> |
| <para> |
| There are two legacy modes (still implemented as of Qpid 0.14) |
| controlled by the qpid.last_value_queue and |
| qpid.last_value_queue_no_browse argument values. These modes are |
| deprecated and should not be used. |
| </para> |
| </section> |
| </section> |