Added: qpid/site/input/releases/qpid-proton-0.9.1/proton/python/tutorial/tutorial.html URL: http://svn.apache.org/viewvc/qpid/site/input/releases/qpid-proton-0.9.1/proton/python/tutorial/tutorial.html?rev=1681791&view=auto ============================================================================== --- qpid/site/input/releases/qpid-proton-0.9.1/proton/python/tutorial/tutorial.html (added) +++ qpid/site/input/releases/qpid-proton-0.9.1/proton/python/tutorial/tutorial.html Tue May 26 16:24:06 2015 @@ -0,0 +1,1059 @@ + + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + + <title>Tutorial — Apache Qpid Proton 0.9 documentation</title> + + <link rel="stylesheet" href="_static/sphinxdoc.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + + <script type="text/javascript"> + var DOCUMENTATION_OPTIONS = { + URL_ROOT: '', + VERSION: '0.9', + COLLAPSE_INDEX: false, + FILE_SUFFIX: '.html', + HAS_SOURCE: true + }; + </script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <link rel="top" title="Apache Qpid Proton 0.9 documentation" href="index.html" /> + <link rel="next" title="API Overview" href="overview.html" /> + <link rel="prev" title="Welcome to Apache Qpid Protonâs documentation!" href="index.html" /> + </head> + <body> + <div class="related"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + accesskey="I">index</a></li> + <li class="right" > + <a href="overview.html" title="API Overview" + accesskey="N">next</a> |</li> + <li class="right" > + <a href="index.html" title="Welcome to Apache Qpid Protonâs documentation!" + accesskey="P">previous</a> |</li> + <li><a href="index.html">Apache Qpid Proton 0.9 documentation</a> »</li> + </ul> + </div> + <div class="sphinxsidebar"> + <div class="sphinxsidebarwrapper"> + <h3><a href="index.html">Table Of Contents</a></h3> + <ul> +<li><a class="reference internal" href="#">Tutorial</a><ul> +<li><a class="reference internal" href="#hello-world">Hello World!</a></li> +<li><a class="reference internal" href="#hello-world-direct">Hello World, Direct!</a></li> +<li><a class="reference internal" href="#asynchronous-send-and-receive">Asynchronous Send and Receive</a></li> +<li><a class="reference internal" href="#request-response">Request/Response</a><ul> +<li><a class="reference internal" href="#miscellaneous">Miscellaneous</a></li> +</ul> +</li> +</ul> +</li> +</ul> + + <h4>Previous topic</h4> + <p class="topless"><a href="index.html" + title="previous chapter">Welcome to Apache Qpid Proton’s documentation!</a></p> + <h4>Next topic</h4> + <p class="topless"><a href="overview.html" + title="next chapter">API Overview</a></p> + <h3>This Page</h3> + <ul class="this-page-menu"> + <li><a href="_sources/tutorial.txt" + rel="nofollow">Show Source</a></li> + </ul> +<div id="searchbox" style="display: none"> + <h3>Quick search</h3> + <form class="search" action="search.html" method="get"> + <input type="text" name="q" /> + <input type="submit" value="Go" /> + <input type="hidden" name="check_keywords" value="yes" /> + <input type="hidden" name="area" value="default" /> + </form> + <p class="searchtip" style="font-size: 90%"> + Enter search terms or a module, class or function name. + </p> +</div> +<script type="text/javascript">$('#searchbox').show(0);</script> + </div> + </div> + + <div class="document"> + <div class="documentwrapper"> + <div class="bodywrapper"> + <div class="body"> + + <div class="section" id="tutorial"> +<h1>Tutorial<a class="headerlink" href="#tutorial" title="Permalink to this headline">¶</a></h1> +<div class="section" id="hello-world"> +<h2>Hello World!<a class="headerlink" href="#hello-world" title="Permalink to this headline">¶</a></h2> +<p>Tradition dictates that we start with hello world! However rather than +simply striving for the shortest program possible, we’ll aim for a +more illustrative example while still restricting the functionality to +sending and receiving a single message.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">HelloWorld</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">server</span> <span class="o">=</span> <span class="n">server</span> + <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">address</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">conn</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="p">)</span> + <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span> + <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_sendable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">body</span><span class="o">=</span><span class="s">u"Hello World!"</span><span class="p">))</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="n">Container</span><span class="p">(</span><span class="n">HelloWorld</span><span class="p">(</span><span class="s">"localhost:5672"</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +</pre></div> +</td></tr></table></div> +<p>You can see the import of <tt class="xref py py-class docutils literal"><span class="pre">Container</span></tt> from <tt class="docutils literal"><span class="pre">proton.reactor</span></tt> on the +second line. This is a class that makes programming with proton a +little easier for the common cases. It includes within it an event +loop, and programs written using this utility are generally structured +to react to various events. This reactive style is particularly suited +to messaging applications.</p> +<p>To be notified of a particular event, you define a class with the +appropriately name method on it. That method is then called by the +event loop when the event occurs.</p> +<p>We define a class here, <tt class="docutils literal"><span class="pre">HelloWorld</span></tt>, which handles the key events of +interest in sending and receiving a message.</p> +<p>The <tt class="docutils literal"><span class="pre">on_start()</span></tt> method is called when the event loop first +starts. We handle that by establishing our connection (line 12), a +sender over which to send the message (line 13) and a receiver over +which to receive it back again (line 14).</p> +<p>The <tt class="docutils literal"><span class="pre">on_sendable()</span></tt> method is called when message can be transferred +over the associated sender link to the remote peer. We send out our +<tt class="docutils literal"><span class="pre">Hello</span> <span class="pre">World!</span></tt> message (line 17), then close the sender (line 18) as +we only want to send one message. The closing of the sender will +prevent further calls to <tt class="docutils literal"><span class="pre">on_sendable()</span></tt>.</p> +<p>The <tt class="docutils literal"><span class="pre">on_message()</span></tt> method is called when a message is +received. Within that we simply print the body of the message (line +21) and then close the connection (line 22).</p> +<p>Now that we have defined the logic for handling these events, we +create an instance of a <tt class="xref py py-class docutils literal"><span class="pre">Container</span></tt>, pass it +our handler and then enter the event loop by calling +<tt class="xref py py-meth docutils literal"><span class="pre">run()</span></tt>. At this point control +passes to the container instance, which will make the appropriate +callbacks to any defined handlers.</p> +<p>To run the example you will need to have a broker (or similar) +accepting connections on that url either with a queue (or topic) +matching the given address or else configured to create such a queue +(or topic) dynamically. There is a simple broker.py script included +alongside the examples that can be used for this purpose if +desired. (It is also written using the API described here, and as such +gives an example of a slightly more involved application).</p> +</div> +<div class="section" id="hello-world-direct"> +<h2>Hello World, Direct!<a class="headerlink" href="#hello-world-direct" title="Permalink to this headline">¶</a></h2> +<p>Though often used in conjunction with a broker, AMQP does not +<em>require</em> this. It also allows senders and receivers can communicate +directly if desired.</p> +<p>Let’s modify our example to demonstrate this.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">HelloWorld</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> +<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> +</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_sendable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">body</span><span class="o">=</span><span class="s">u"Hello World!"</span><span class="p">))</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + +<span class="hll"> <span class="k">def</span> <span class="nf">on_accepted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> +</span><span class="hll"> <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +</span> +<span class="hll"> <span class="k">def</span> <span class="nf">on_connection_closed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> +</span><span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +</span> +<span class="n">Container</span><span class="p">(</span><span class="n">HelloWorld</span><span class="p">(</span><span class="s">"localhost:8888/examples"</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +</pre></div> +</td></tr></table></div> +<p>The first difference, on line 11, is that rather than creating a +receiver on the same connection as our sender, we listen for incoming +connections by invoking the +<tt class="xref py py-meth docutils literal"><span class="pre">listen()</span></tt> method on the +container.</p> +<p>As we only need then to initiate one link, the sender, we can do that +by passing in a url rather than an existing connection, and the +connection will also be automatically established for us.</p> +<p>We send the message in response to the <tt class="docutils literal"><span class="pre">on_sendable()</span></tt> callback and +print the message out in response to the <tt class="docutils literal"><span class="pre">on_message()</span></tt> callback +exactly as before.</p> +<p>However we also handle two new events. We now close the connection +from the senders side once the message has been accepted (line +22). The acceptance of the message is an indication of successful +transfer to the peer. We are notified of that event through the +<tt class="docutils literal"><span class="pre">on_accepted()</span></tt> callback. Then, once the connection has been closed, +of which we are notified through the <tt class="docutils literal"><span class="pre">on_closed()</span></tt> callback, we stop +accepting incoming connections (line 25) at which point there is no +work to be done and the event loop exits, and the run() method will +return.</p> +<p>So now we have our example working without a broker involved!</p> +</div> +<div class="section" id="asynchronous-send-and-receive"> +<h2>Asynchronous Send and Receive<a class="headerlink" href="#asynchronous-send-and-receive" title="Permalink to this headline">¶</a></h2> +<p>Of course, these <tt class="docutils literal"><span class="pre">HelloWorld!</span></tt> examples are very artificial, +communicating as they do over a network connection but with the same +process. A more realistic example involves communication between +separate processes (which could indeed be running on completely +separate machines).</p> +<p>Let’s separate the sender from the receiver, and let’s transfer more than +a single message between them.</p> +<p>We’ll start with a simple sender.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">optparse</span> +<span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">Send</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">messages</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Send</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">=</span> <span class="mi">0</span> + <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">=</span> <span class="mi">0</span> + <span class="bp">self</span><span class="o">.</span><span class="n">total</span> <span class="o">=</span> <span class="n">messages</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_sendable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">while</span> <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">credit</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">total</span><span class="p">:</span> + <span class="n">msg</span> <span class="o">=</span> <span class="n">Message</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sent</span><span class="o">+</span><span class="mi">1</span><span class="p">),</span> <span class="n">body</span><span class="o">=</span><span class="p">{</span><span class="s">'sequence'</span><span class="p">:(</span><span class="bp">self</span><span class="o">.</span><span class="n">sent</span><span class="o">+</span><span class="mi">1</span><span class="p">)})</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">+=</span> <span class="mi">1</span> + + <span class="k">def</span> <span class="nf">on_accepted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">+=</span> <span class="mi">1</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">total</span><span class="p">:</span> + <span class="k">print</span> <span class="s">"all messages confirmed"</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_disconnected</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> + +<span class="n">parser</span> <span class="o">=</span> <span class="n">optparse</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="o">=</span><span class="s">"usage: %prog [options]"</span><span class="p">,</span> + <span class="n">description</span><span class="o">=</span><span class="s">"Send messages to the supplied address."</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-a"</span><span class="p">,</span> <span class="s">"--address"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">"localhost:5672/examples"</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"address to which messages are sent (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-m"</span><span class="p">,</span> <span class="s">"--messages"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"int"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"number of messages to send (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Send</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">messages</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>As with the previous example, we define the application logic in a +class that handles various events. As before, we use the +<tt class="docutils literal"><span class="pre">on_start()</span></tt> event to establish our sender link over which we will +transfer messages and the <tt class="docutils literal"><span class="pre">on_sendable()</span></tt> event to know when we can +transfer our messages.</p> +<p>Because we are transferring more than one message, we need to keep +track of how many we have sent. We’ll use a <tt class="docutils literal"><span class="pre">sent</span></tt> member variable +for that. The <tt class="docutils literal"><span class="pre">total</span></tt> member variable will hold the number of +messages we want to send.</p> +<p>AMQP defines a credit-based flow control mechanism. Flow control +allows the receiver to control how many messages it is prepared to +receive at a given time and thus prevents any component being +overwhelmed by the number of messages it is sent.</p> +<p>In the <tt class="docutils literal"><span class="pre">on_sendable()</span></tt> callback, we check that our sender has credit +before sending messages. We also check that we haven’t already sent +the required number of messages.</p> +<p>The <tt class="docutils literal"><span class="pre">send()</span></tt> call on line 20 is of course asynchronous. When it +returns the message has not yet actually been transferred across the +network to the receiver. By handling the <tt class="docutils literal"><span class="pre">on_accepted()</span></tt> event, we +can get notified when the receiver has received and accepted the +message. In our example we use this event to track the confirmation of +the messages we have sent. We only close the connection and exit when +the receiver has received all the messages we wanted to send.</p> +<p>If we are disconnected after a message is sent and before it has been +confirmed by the receiver, it is said to be <tt class="docutils literal"><span class="pre">in</span> <span class="pre">doubt</span></tt>. We don’t +know whether or not it was received. In this example, we will handle +that by resending any in-doubt messages. This is known as an +‘at-least-once’ guarantee, since each message should eventually be +received at least once, though a given message may be received more +than once (i.e. duplicates are possible). In the <tt class="docutils literal"><span class="pre">on_disconnected()</span></tt> +callback, we reset the sent count to reflect only those that have been +confirmed. The library will automatically try to reconnect for us, and +when our sender is sendable again, we can restart from the point we +know the receiver got to.</p> +<p>Now let’s look at the corresponding receiver:</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">optparse</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">Recv</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Recv</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">expected</span> <span class="o">=</span> <span class="n">count</span> + <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o">=</span> <span class="mi">0</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">id</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">id</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">received</span><span class="p">:</span> + <span class="c"># ignore duplicate message</span> + <span class="k">return</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">expected</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">expected</span><span class="p">:</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o">+=</span> <span class="mi">1</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">expected</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="n">parser</span> <span class="o">=</span> <span class="n">optparse</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="o">=</span><span class="s">"usage: %prog [options]"</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-a"</span><span class="p">,</span> <span class="s">"--address"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">"localhost:5672/examples"</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"address from which messages are received (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-m"</span><span class="p">,</span> <span class="s">"--messages"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"int"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"number of messages to receive; 0 receives indefinitely (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Recv</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">messages</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>Here we handle the <tt class="docutils literal"><span class="pre">on_start()</span></tt> by creating our receiver, much like +we did for the sender. We also handle the <tt class="docutils literal"><span class="pre">on_message()</span></tt> event for +received messages and print the message out as in the <tt class="docutils literal"><span class="pre">Hello</span> <span class="pre">World!</span></tt> +examples. However we add some logic to allow the receiver to wait for +a given number of messages, then to close the connection and exit. We +also add some logic to check for and ignore duplicates, using a simple +sequential id scheme.</p> +<p>Again, though sending between these two examples requires some sort of +intermediary process (e.g. a broker), AMQP allows us to send messages +directly between two processes without this if we so wish. In that +case one or other of the processes needs to accept incoming socket +connections. Let’s create a modified version of the receiving example +that does this:</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">optparse</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">Recv</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">count</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Recv</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">expected</span> <span class="o">=</span> <span class="n">count</span> + <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o">=</span> <span class="mi">0</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> +<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> +</span> + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">id</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">id</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">received</span><span class="p">:</span> + <span class="c"># ignore duplicate message</span> + <span class="k">return</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">expected</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">expected</span><span class="p">:</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o">+=</span> <span class="mi">1</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">received</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">expected</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +</span> +<span class="n">parser</span> <span class="o">=</span> <span class="n">optparse</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="o">=</span><span class="s">"usage: %prog [options]"</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-a"</span><span class="p">,</span> <span class="s">"--address"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">"localhost:5672/examples"</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"address from which messages are received (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-m"</span><span class="p">,</span> <span class="s">"--messages"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"int"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"number of messages to receive; 0 receives indefinitely (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Recv</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">messages</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>There are only two differences here. On line 13, instead of initiating +a link (and implicitly a connection), we listen for incoming +connections. On line 25, when we have received all the expected +messages, we then stop listening for incoming connections by closing +the acceptor object.</p> +<p>You can use the original send example now to send to this receiver +directly. (Note: you will need to stop any broker that is listening on +the 5672 port, or else change the port used by specifying a different +address to each example via the -a command line switch).</p> +<p>We could equally well modify the original sender to allow the original +receiver to connect to it. Again that just requires two modifications:</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">optparse</span> +<span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">Send</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">messages</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Send</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">=</span> <span class="mi">0</span> + <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">=</span> <span class="mi">0</span> + <span class="bp">self</span><span class="o">.</span><span class="n">total</span> <span class="o">=</span> <span class="n">messages</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> +<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> +</span> + <span class="k">def</span> <span class="nf">on_sendable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">while</span> <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">credit</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">total</span><span class="p">:</span> + <span class="n">msg</span> <span class="o">=</span> <span class="n">Message</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sent</span><span class="o">+</span><span class="mi">1</span><span class="p">),</span> <span class="n">body</span><span class="o">=</span><span class="p">{</span><span class="s">'sequence'</span><span class="p">:(</span><span class="bp">self</span><span class="o">.</span><span class="n">sent</span><span class="o">+</span><span class="mi">1</span><span class="p">)})</span> + <span class="n">event</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">+=</span> <span class="mi">1</span> + + <span class="k">def</span> <span class="nf">on_accepted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">+=</span> <span class="mi">1</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">total</span><span class="p">:</span> + <span class="k">print</span> <span class="s">"all messages confirmed"</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +<span class="hll"> <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +</span> + <span class="k">def</span> <span class="nf">on_disconnected</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">confirmed</span> + +<span class="n">parser</span> <span class="o">=</span> <span class="n">optparse</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="o">=</span><span class="s">"usage: %prog [options]"</span><span class="p">,</span> + <span class="n">description</span><span class="o">=</span><span class="s">"Send messages to the supplied address."</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-a"</span><span class="p">,</span> <span class="s">"--address"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">"localhost:5672/examples"</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"address to which messages are sent (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-m"</span><span class="p">,</span> <span class="s">"--messages"</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"int"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"number of messages to send (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Send</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">opts</span><span class="o">.</span><span class="n">messages</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>As with the modified receiver, instead of initiating establishment of +a link, we listen for incoming connections on line 15 and then on line +28, when we have received confirmation of all the messages we sent, we +can close the acceptor in order to exit. The symmetry in the +underlying AMQP that enables this is quite unique and elegant, and in +reflecting this the proton API provides a flexible toolkit for +implementing all sorts of interesting intermediaries (the broker.py +script provided as a simple broker for testing purposes provides an +example of this).</p> +<p>To try this modified sender, run the original receiver against it.</p> +</div> +<div class="section" id="request-response"> +<h2>Request/Response<a class="headerlink" href="#request-response" title="Permalink to this headline">¶</a></h2> +<p>A common pattern is to send a request message and expect a response +message in return. AMQP has special support for this pattern. Let’s +have a look at a simple example. We’ll start with the ‘server’, +i.e. the program that will process the request and send the +response. Note that we are still using a broker in this example.</p> +<p>Our server will provide a very simple service: it will respond with +the body of the request converted to uppercase.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">Server</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Server</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">address</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span> <span class="o">=</span> <span class="p">{}</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="s">"Listening on"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">container</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span> + <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">receiver</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">relay</span> <span class="o">=</span> <span class="bp">None</span> + + <span class="k">def</span> <span class="nf">on_connection_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">remote_offered_capabilities</span> <span class="ow">and</span> <span class="s">'ANONYMOUS-RELAY'</span> <span class="ow">in</span> <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">remote_offered_capabilities</span><span class="p">:</span> + <span class="bp">self</span><span class="o">.</span><span class="n">relay</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="s">"Received"</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span> + <span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">relay</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">)</span> + <span class="k">if</span> <span class="ow">not</span> <span class="n">sender</span><span class="p">:</span> + <span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">]</span> <span class="o">=</span> <span class="n">sender</span> + <span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">upper</span><span class="p">(),</span> + <span class="n">correlation_id</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">correlation_id</span><span class="p">))</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Server</span><span class="p">(</span><span class="s">"0.0.0.0:5672"</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>The code here is not too different from the simple receiver +example. When we receive a request however, we look at the +<tt class="xref py py-attr docutils literal"><span class="pre">reply_to</span></tt> address on the +<tt class="xref py py-class docutils literal"><span class="pre">Message</span></tt> and create a sender for that over which to +send the response. We’ll cache the senders incase we get further +requests with the same reply_to.</p> +<p>Now let’s create a simple client to test this service out.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">optparse</span> +<span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span><span class="p">,</span> <span class="n">DynamicNodeProperties</span> + +<span class="k">class</span> <span class="nc">Client</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">requests</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Client</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">requests</span> <span class="o">=</span> <span class="n">requests</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sender</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_sender</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> + <span class="bp">self</span><span class="o">.</span><span class="n">receiver</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">connection</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="n">dynamic</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">next_request</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">remote_source</span><span class="o">.</span><span class="n">address</span><span class="p">:</span> + <span class="n">req</span> <span class="o">=</span> <span class="n">Message</span><span class="p">(</span><span class="n">reply_to</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">remote_source</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">requests</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> + <span class="bp">self</span><span class="o">.</span><span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_link_opened</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">receiver</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">receiver</span><span class="p">:</span> + <span class="bp">self</span><span class="o">.</span><span class="n">next_request</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="s">"</span><span class="si">%s</span><span class="s"> => </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">requests</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span><span class="p">)</span> + <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">requests</span><span class="p">:</span> + <span class="bp">self</span><span class="o">.</span><span class="n">next_request</span><span class="p">()</span> + <span class="k">else</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="n">REQUESTS</span><span class="o">=</span> <span class="p">[</span><span class="s">"Twas brillig, and the slithy toves"</span><span class="p">,</span> + <span class="s">"Did gire and gymble in the wabe."</span><span class="p">,</span> + <span class="s">"All mimsy were the borogroves,"</span><span class="p">,</span> + <span class="s">"And the mome raths outgrabe."</span><span class="p">]</span> + +<span class="n">parser</span> <span class="o">=</span> <span class="n">optparse</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="o">=</span><span class="s">"usage: %prog [options]"</span><span class="p">,</span> + <span class="n">description</span><span class="o">=</span><span class="s">"Send requests to the supplied address and print responses."</span><span class="p">)</span> +<span class="n">parser</span><span class="o">.</span><span class="n">add_option</span><span class="p">(</span><span class="s">"-a"</span><span class="p">,</span> <span class="s">"--address"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">"localhost:5672/examples"</span><span class="p">,</span> + <span class="n">help</span><span class="o">=</span><span class="s">"address to which messages are sent (default </span><span class="si">%d</span><span class="s">efault)"</span><span class="p">)</span> +<span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> + +<span class="n">Container</span><span class="p">(</span><span class="n">Client</span><span class="p">(</span><span class="n">opts</span><span class="o">.</span><span class="n">address</span><span class="p">,</span> <span class="n">args</span> <span class="ow">or</span> <span class="n">REQUESTS</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +</pre></div> +</td></tr></table></div> +<p>As well as sending requests, we need to be able to get back the +responses. We create a receiver for that (see line 14), but we don’t +specify an address, we set the dynamic option which tells the broker +we are connected to to create a temporary address over which we can +receive our responses.</p> +<p>We need to use the address allocated by the broker as the reply_to +address of our requests, so we can’t send them until the broker has +confirmed our receiving link has been set up (at which point we will +have our allocated address). To do that, we add an +<tt class="docutils literal"><span class="pre">on_link_opened()</span></tt> method to our handler class, and if the link +associated with event is the receiver, we use that as the trigger to +send our first request.</p> +<p>Again, we could avoid having any intermediary process here if we +wished. The following code implementas a server to which the client +above could connect directly without any need for a broker or similar.</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton</span> <span class="kn">import</span> <span class="n">generate_uuid</span><span class="p">,</span> <span class="n">Message</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> +<span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span> + +<span class="k">class</span> <span class="nc">Server</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Server</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span> <span class="o">=</span> <span class="p">{}</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="s">"Listening on"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">url</span> + <span class="bp">self</span><span class="o">.</span><span class="n">container</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span> + <span class="bp">self</span><span class="o">.</span><span class="n">acceptor</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span> + + <span class="k">def</span> <span class="nf">on_link_opening</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">is_sender</span><span class="p">:</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_source</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_source</span><span class="o">.</span><span class="n">dynamic</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">generate_uuid</span><span class="p">())</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">address</span><span class="p">]</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span> + <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_target</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_target</span><span class="o">.</span><span class="n">address</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_target</span><span class="o">.</span><span class="n">address</span> + <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_target</span><span class="o">.</span><span class="n">address</span><span class="p">]</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span> + <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_source</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">source</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_source</span><span class="o">.</span><span class="n">address</span> + <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_target</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">link</span><span class="o">.</span><span class="n">remote_target</span><span class="o">.</span><span class="n">address</span> + + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="s">"Received"</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span> + <span class="n">sender</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">senders</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">)</span> + <span class="k">if</span> <span class="ow">not</span> <span class="n">sender</span><span class="p">:</span> + <span class="k">print</span> <span class="s">"No link for reply"</span> + <span class="k">return</span> + <span class="n">sender</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">Message</span><span class="p">(</span><span class="n">address</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">reply_to</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">upper</span><span class="p">(),</span> + <span class="n">correlation_id</span><span class="o">=</span><span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">correlation_id</span><span class="p">))</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Server</span><span class="p">(</span><span class="s">"0.0.0.0:8888"</span><span class="p">))</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>Though this requires some more extensive changes than the simple +sending and receiving examples, the essence of the program is still +the same. Here though, rather than the server establishing a link for +the response, it relies on the link that the client established, since +that now comes in directly to the server process.</p> +<div class="section" id="miscellaneous"> +<h3>Miscellaneous<a class="headerlink" href="#miscellaneous" title="Permalink to this headline">¶</a></h3> +<p>Many brokers offer the ability to consume messages based on a +‘selector’ that defines which messages are of interest based on +particular values of the headers. The following example shows how that +can be achieved:</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span><span class="p">,</span> <span class="n">Selector</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> + +<span class="k">class</span> <span class="nc">Recv</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Recv</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">conn</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"localhost:5672"</span><span class="p">)</span> +<span class="hll"> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">Selector</span><span class="p">(</span><span class="s">u"colour = 'green'"</span><span class="p">))</span> +</span> + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">body</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Recv</span><span class="p">())</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +<p>When creating the receiver, we specify a Selector object as an +option. The options argument can take a single object or a +list. Another option that is sometimes of interest when using a broker +is the ability to ‘browse’ the messages on a queue, rather than +consumig them. This is done in AMQP by specifying a distribution mode +of ‘copy’ (instead of ‘move’ which is the expected default for +queues). An example of that is shown next:</p> +<div class="highlight-python"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19</pre></div></td><td class="code"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">proton.reactor</span> <span class="kn">import</span> <span class="n">Container</span><span class="p">,</span> <span class="n">Copy</span> +<span class="kn">from</span> <span class="nn">proton.handlers</span> <span class="kn">import</span> <span class="n">MessagingHandler</span> + +<span class="k">class</span> <span class="nc">Recv</span><span class="p">(</span><span class="n">MessagingHandler</span><span class="p">):</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="nb">super</span><span class="p">(</span><span class="n">Recv</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span> + + <span class="k">def</span> <span class="nf">on_start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="n">conn</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"localhost:5672"</span><span class="p">)</span> +<span class="hll"> <span class="n">event</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">create_receiver</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="s">"examples"</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">Copy</span><span class="p">())</span> +</span> + <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span> + <span class="k">print</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span> + <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">queued</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">receiver</span><span class="o">.</span><span class="n">drained</span><span class="p">:</span> + <span class="n">event</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">Container</span><span class="p">(</span><span class="n">Recv</span><span class="p">())</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> +<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> <span class="k">pass</span> +</pre></div> +</td></tr></table></div> +</div> +</div> +</div> + + + </div> + </div> + </div>
[... 25 lines stripped ...] --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org