Sorry about the ambiguity,<div><br></div><div>For the sake of clarity here is the glossary of terms I used in my last email (which probably clashes with the erlang/amqp_client context you&#39;re coming from):</div><div><br>
</div><div>Server - I&#39;m referring to my long running process in erlang that I have given a registered name and passed as the 3rd argument to amqp_client:subscribe/3.<br><div>Listener - the process created by the amqp_client library when a connection and channel are opened</div>
<div>Subscribe - calling of amqp_client:subscribe/3</div><div>My - I&#39;m using this pronoun to distinguish code written by me from code written by you cats at rabbitmq (client library, rabbitmq server, etc)</div><div><br>
</div><div>I&#39;ve attached a diagram (approximation/abstraction) of how I&#39;m interacting with the amqp_client library. (sorry to the mailing list if attaching a 40K diagram breaks etiquette).</div><div><br></div><div>
I&#39;m using the amqp_client library in network mode, i.e., amqp_client:start(network, #amqp_params{host = Host, heartbeat=60000})</div><div><br></div><div>Yes a list of messages that the amqp_client process sends to a subscriber, particularly pertaining to errors in amqp_client land, would be very helpful.  I&#39;d like to be able to handle all {&#39;DOWN&#39;,Etc} messages with my long running process (server).  I&#39;m hoping to handle all hard errors so that a restart from either supervisor (my long running process or the amqp_client&#39;s) won&#39;t break the communication between the two.</div>
<div><br></div><div>But I get the impression that I&#39;m missing something about how I&#39;m supposed to treat the amqp_client library with regard to amqp_client:start/2.  Should I be treating the amqp_client connection like mnesia (an application entirely independent of mine), add it to my existing supervision tree and share one connection throughout my application, or, what I&#39;m currently doing, let each part of my application that needs to talk to amqp spin up and close their own connection/channel?<br>
<br></div><div>Thanks,</div><div>-Max</div><div><br><div class="gmail_quote">On Mon, Jul 4, 2011 at 12:16 PM, Alexandru Scvorţov <span dir="ltr">&lt;<a href="mailto:alexandru@rabbitmq.com">alexandru@rabbitmq.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Hi Max,<br>
<br>
I&#39;m trying to run through the steps you provided, but I&#39;m having a bit<br>
of trouble following.<br>
<br>
Are you using a network or a direct connection? (I assume network, but<br>
it probably doesn&#39;t matter)<br>
<br>
By server, do you mean the actual RabbitMQ server, or you application?<br>
(I&#39;m guessing your long-running application)<br>
<br>
By subscribe, do you mean calling amqp_channel:subscribe/3?  If so, do<br>
you still need a list of the messages the channel may send its<br>
subscriber?<br>
<br>
Or do you mean that your application is sending messages to its<br>
subscribers?<br>
<div class="im"><br>
&gt; 6.) The server supervisor restarts the server which creates a new listener,<br>
&gt; but the old listener is still hanging around trying to send the the<br>
&gt; registered name<br>
<br>
</div>What&#39;s a listener?  Is it a process that receives messages from the<br>
erlang client because it&#39;s the endpoint of a subscription to a queue?<br>
<br>
Can&#39;t you link listeners to the server so that when the server goes<br>
down, it takes the listeners with it?<br>
<div class="im"><br>
&gt; So my question then is how should I kill the amqp_client?<br>
<br>
</div>What do you mean by amqp_client?  If it&#39;s an amqp_connection process,<br>
you can just send it an shutdown exit.<br>
<br>
Thanks for the information.<br>
<br>
Cheers,<br>
Alex<br>
<div><div></div><div class="h5"><br>
On Fri, Jul 01, 2011 at 01:51:10PM -0400, Max Warnock wrote:<br>
&gt; Problem found.  Thanks for your help.  The problem is a strange one and has<br>
&gt; to do with me not shutting my amqp_client listener down properly if my<br>
&gt; server dies.  Here is how it manifests:<br>
&gt;<br>
&gt; 1.) Server starts up and starts up a amqp client connection and channel<br>
&gt; 2.) The server binds to that channel and starts the subscription using a<br>
&gt; registered name name as the process to which messages will be sent<br>
&gt; 3.) Messages start coming in and are ack-ing fine<br>
&gt; 4.) Poor error handling in farming out processes brings the server down<br>
&gt; 5.) The server does no close the amqp_client connection<br>
&gt; 6.) The server supervisor restarts the server which creates a new listener,<br>
&gt; but the old listener is still hanging around trying to send the the<br>
&gt; registered name<br>
&gt; 7.) The older listener sends a message to the server<br>
&gt; 8.) The server tries to ack to the new listener which did not send the<br>
&gt; message<br>
&gt; 9.) The new server pukes because it never sent a message with that tag<br>
&gt;<br>
&gt; So my question then is how should I kill the amqp_client? If I send it an<br>
&gt; exit its supervisor will restart it.  This is what I was getting at with my<br>
&gt; tangential questions in the last email.  How should I shut down the<br>
&gt; amqp_client without shutting down all the other servers&#39; amqp client<br>
&gt; listeners?<br>
&gt;<br>
&gt; Thanks for all the help,<br>
&gt; -Max<br>
&gt;<br>
&gt; On Thu, Jun 30, 2011 at 9:23 AM, Max Warnock &lt;<a href="mailto:maxjwarnock@gmail.com">maxjwarnock@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; &gt; Thanks, that&#39;s very helpful from both the possible issues to chase and<br>
&gt; &gt; sanity check perspectives.<br>
&gt; &gt;<br>
&gt; &gt; I&#39;m using erlang R13B04 with a rabbitmq server installed via gentoo&#39;s<br>
&gt; &gt; portage at version 2.4.1. I pulled the client library from github (tag<br>
&gt; &gt; 2.3.0, commit: 844738f9b56d34104c1ea2ac5700d0898126c5b4).<br>
&gt; &gt;<br>
&gt; &gt; I&#39;m going to write some debug code to store all the tags I try to ack on<br>
&gt; &gt; and see if I can get this error to where it&#39;s easily reproducible. Thanks<br>
&gt; &gt; for narrowing my search, it&#39;s very helpful.  I&#39;ll keep you updated. I must<br>
&gt; &gt; be doing something wrong somewhere.  I have a hard time believing such a<br>
&gt; &gt; widely used library could fail so hard myself.<br>
&gt; &gt;<br>
&gt; &gt; One thing that would be extremely helpful is if you could point me to some<br>
&gt; &gt; documentation which I haven&#39;t been able to find:  I&#39;m looking for a listing<br>
&gt; &gt; of all the events/messages that are sent out by the amqp client to a<br>
&gt; &gt; subscriber.  What does it send when it goes down, what other soft errors<br>
&gt; &gt; will it send out, etc.  Additionally, is there a doc somewhere for best<br>
&gt; &gt; practices in connecting a listener to another server/long-running process?<br>
&gt; &gt;  Not having either of those there has been some struggle to know how to<br>
&gt; &gt; restart the subscription/listening process if my server dies.  The<br>
&gt; &gt; amqp_client tutorial has been a great help, but when it comes to error<br>
&gt; &gt; handling from the listening module perspective it doesn&#39;t tell me what the<br>
&gt; &gt; library is expecting me to do.  I don&#39;t want to have to do a bunch of<br>
&gt; &gt; engineering because I&#39;m square peg, round hole-ing the library.  The primary<br>
&gt; &gt; issues I&#39;m concerned with are when my server dies hard and is destined to be<br>
&gt; &gt; restarted by its supervisor what should I send to the amqp client process?<br>
&gt; &gt; Should I send it close messages and then start a new one? Or should I<br>
&gt; &gt; reconnect to the client library.  This wouldn&#39;t be as big of an issue but I<br>
&gt; &gt; need to use durable/persistent queues and if I still have a listener hanging<br>
&gt; &gt; around with the same bindings on the same queue it will eat all my messages<br>
&gt; &gt; and send them nowhere.<br>
&gt; &gt;<br>
&gt; &gt; Thanks,<br>
&gt; &gt; -Max<br>
&gt; &gt;<br>
&gt; &gt; On Thu, Jun 30, 2011 at 7:48 AM, Matthew Sackman &lt;<a href="mailto:matthew@rabbitmq.com">matthew@rabbitmq.com</a>&gt;wrote:<br>
&gt; &gt;<br>
&gt; &gt;&gt; Hi Max,<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; On Wed, Jun 29, 2011 at 06:28:59PM -0400, Max Warnock wrote:<br>
&gt; &gt;&gt; &gt; I&#39;ve built a behavior in erlang to subscribe to a given topic exchange<br>
&gt; &gt;&gt; and<br>
&gt; &gt;&gt; &gt; farm out message handling.  I&#39;m using the rabbitmq amqp_client library<br>
&gt; &gt;&gt; for<br>
&gt; &gt;&gt; &gt; erlang and when I put the system under heavy load I get, on occasion,<br>
&gt; &gt;&gt; the<br>
&gt; &gt;&gt; &gt; following error:<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; Could you let us know which version of Rabbit, Erlang and the Erlang<br>
&gt; &gt;&gt; client you&#39;re using?<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; &gt; =ERROR REPORT==== 29-Jun-2011::18:02:18 ===<br>
&gt; &gt;&gt; &gt; ** Generic server &lt;0.1117.0&gt; terminating<br>
&gt; &gt;&gt; &gt; ** Last message in was {&#39;$gen_cast&#39;,<br>
&gt; &gt;&gt; &gt;                            {method,<br>
&gt; &gt;&gt; &gt;                                {&#39;channel.close&#39;,406,<br>
&gt; &gt;&gt; &gt;                                    &lt;&lt;&quot;PRECONDITION_FAILED - unknown<br>
&gt; &gt;&gt; delivery<br>
&gt; &gt;&gt; &gt; tag 856&quot;&gt;&gt;,<br>
&gt; &gt;&gt; &gt;                                    60,80},<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; That&#39;s a double-ack (probably). Sadly, the AMQP 0-9-1 spec says that<br>
&gt; &gt;&gt; acking is not idempotent, thus it&#39;s a fault to ack the same message<br>
&gt; &gt;&gt; multiple times...<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; &gt; The server receive loop where the ack happens looks like this:<br>
&gt; &gt;&gt; &gt; receive<br>
&gt; &gt;&gt; &gt; ...<br>
&gt; &gt;&gt; &gt; {#&#39;basic.deliver&#39;{delivery_tag = Tag, routing_key = RoutingKey},<br>
&gt; &gt;&gt; &gt; #amqp_msg{payload = Payload}} -&gt;<br>
&gt; &gt;&gt; &gt;     amqp_channel:cast(get(amqp_channel_pid), #&#39;basic.ack&#39;{delivery_tag =<br>
&gt; &gt;&gt; &gt; Tag}),<br>
&gt; &gt;&gt; &gt;     spawn_and_queue(spawn_handle_message, Module, RoutingKey, Payload),<br>
&gt; &gt;&gt; &gt;     loop(Module);<br>
&gt; &gt;&gt; &gt; ...<br>
&gt; &gt;&gt; &gt; end<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; ...hmmm, which is so simple that I can&#39;t see how it could go wrong: if<br>
&gt; &gt;&gt; you&#39;re not double acking then something else must be going on to make<br>
&gt; &gt;&gt; the broker think that it&#39;s not expecting an ack for that message, hence<br>
&gt; &gt;&gt; the error. If you&#39;re doing some sort of reject operation - either<br>
&gt; &gt;&gt; basic.nack or basic.reject on messages and you then subsequently ack one<br>
&gt; &gt;&gt; of those messages then that would also cause this error. There may be<br>
&gt; &gt;&gt; other cases as well.<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; &gt; The amqp_client_sup can&#39;t seem to bring back the the client either and<br>
&gt; &gt;&gt; dies<br>
&gt; &gt;&gt; &gt; from the retry intensity being reached.  I&#39;ve done a hefty amount of<br>
&gt; &gt;&gt; &gt; googling and can&#39;t seem to find where things could be going wrong.<br>
&gt; &gt;&gt;  Before<br>
&gt; &gt;&gt; &gt; jumping into the amqp_client code I thought I&#39;d ask the mailing list if<br>
&gt; &gt;&gt; they<br>
&gt; &gt;&gt; &gt; have any ideas.  The only thing I can think is that there is a race<br>
&gt; &gt;&gt; &gt; condition within the client library.  I will be double checking my code<br>
&gt; &gt;&gt; to<br>
&gt; &gt;&gt; &gt; be sure it isn&#39;t sending the ack twice, but given the simplicity of the<br>
&gt; &gt;&gt; ack<br>
&gt; &gt;&gt; &gt; the only way it could is if it receives the same message (with identical<br>
&gt; &gt;&gt; &gt; delivery tag) from the amqp_client library twice.<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; It could be a bug in the client library, but I&#39;d be a little surprised<br>
&gt; &gt;&gt; if we&#39;re managing to duplicate messages somehow - that would be a new<br>
&gt; &gt;&gt; level of fail for us. ;) However, the fact that the entire connection<br>
&gt; &gt;&gt; dies is alarming and almost certainly a bug: PRECONDITION_FAILED is a<br>
&gt; &gt;&gt; soft error and should only tear down the channel, not the whole<br>
&gt; &gt;&gt; connection. After that, all you should have to do is create a new<br>
&gt; &gt;&gt; channel and everything else should be ok. If that&#39;s not the case please<br>
&gt; &gt;&gt; let us know.<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; Best wishes,<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; Matthew<br>
&gt; &gt;&gt; _______________________________________________<br>
&gt; &gt;&gt; rabbitmq-discuss mailing list<br>
&gt; &gt;&gt; <a href="mailto:rabbitmq-discuss@lists.rabbitmq.com">rabbitmq-discuss@lists.rabbitmq.com</a><br>
&gt; &gt;&gt; <a href="https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss" target="_blank">https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss</a><br>
&gt; &gt;&gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
<br>
&gt; _______________________________________________<br>
&gt; rabbitmq-discuss mailing list<br>
&gt; <a href="mailto:rabbitmq-discuss@lists.rabbitmq.com">rabbitmq-discuss@lists.rabbitmq.com</a><br>
&gt; <a href="https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss" target="_blank">https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss</a><br>
<br>
</div></div></blockquote></div><br></div></div>