summaryrefslogtreecommitdiff
path: root/doc/book/src/cpp-broker/LVQ.xml
blob: b57c6268beda0be943e9d56d8387d003ccec4e43 (plain)
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>
           &lt;empty queue&gt;
      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>