1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
<?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>
|