Hi Alex,<div><br></div><div><br></div><div>Firstly, thank you very much for your answer. You&#39;ve really helped me.</div><div><div>As you suggested we&#39;ll update RabbitMQ to version 2.2.0 as soon as possible.</div><div>
It is great you are introducing publisher confirms in next release because it will offer more fine control to message publishing.</div></div><div><br></div><div><br></div><div>Regarding transfer responsibility I have one more doubt.</div>


<div>As you said, &quot;TxCommit will succeed if messages are lost during routing (due to non-existing queues)&quot;, </div><div>so does it mean that TxCommit launches an exception when it fails?</div><div><br></div><div>
In this case in my code I should handle unexpected exceptions (txSelect, basic.publish, txCommit) and also basic.return in cause immediate and/or mandatory message can&#39;t be delivered, right?</div><div> </div><div><br>
</div><div><br></div><div>Regards,</div><div><br></div><div>Alfonso</div><div><br></div><div><br></div><div><br><br><div class="gmail_quote">

2011/1/27 Alexandru Scvorţov <span dir="ltr">&lt;<a href="mailto:alexandru@rabbitmq.com" target="_blank">alexandru@rabbitmq.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


Hi Alfonso,<br>
<div><br>
&gt; I&#39;ve been googling a lot and some people suggested using this schema:<br>
&gt;<br>
&gt; ch.TxSelect()<br>
&gt; ch.BasicPublish(.....)<br>
&gt; ch.TxCommit()<br>
</div>...<br>
<div>&gt; Reading the API user guide I&#39;ve found that this is called &quot;transfer<br>
&gt; responsibility&quot;.<br>
<br>
</div>That&#39;s correct.  The only way right now to transfer responsibility for<br>
a message to the broker is using transactions.<br>
<br>
That said, I don&#39;t think it&#39;s exactly what you want.  The TxCommit will<br>
succeed if messages are lost during routing (due to non-existing<br>
queues).<br>
<div><br>
<br>
&gt; My question is:<br>
&gt;<br>
&gt; Being TxCommit a void function I tested this block of code using a<br>
&gt; non-existing routing key and I didn&#39;t get any exception.<br>
&gt; Since safe publishing would be highly desiderable non routed messages should<br>
&gt; be detected because the application ACKs the messages of &quot;events queue&quot;<br>
&gt; when after evaluating its content has successfully sent another message to<br>
&gt; the &quot;results queue&quot; (currently if a a routing key is not being routed to a<br>
&gt; queue the messages are silently dropped and I have no way to detect the<br>
&gt; failure so the application ACKs the messages from &quot;events queue&quot;)<br>
&gt;<br>
&gt; Please, can someone tell me how I can&#39;t get that &quot;CommitOK&quot; responses?<br>
<br>
</div>As far as I know, there&#39;s no way cause the broker to throw an exception<br>
for unroutable messages.<br>
<br>
What you could do instead is this:<br>
  - as you&#39;ve suggested, publish with mandatory, immediate, and<br>
    persistent set;<br>
  - do publishes to persistent queues;<br>
  - wrap publishes in that tx code;<br>
  - have the publisher watch for basic.returns and handle somehow lost<br>
    messages (maybe rollback the transaction, republish to a different<br>
    and commit).<br>
<br>
The message flags and the transactions should ensure that the broker<br>
either save the messages to disk or send it to a consumer.  The<br>
ReturnHandler should allow you to republish or somehow handle lost<br>
messages.<br>
<br>
Basic.publish/basic.return aren&#39;t synchronous out of the box and aren&#39;t<br>
meant to be used like that.  For unroutable messages, the broker sends<br>
the basic.return immediately after processing the basic.publish, so if<br>
you publish to a non-existent queue, you should expect the basic.return<br>
soonish; you could use this to make publishes/returns somewhat<br>
synchronous, but I wouldn&#39;t recommend it.<br>
<br>
BTW, the AMQP spec says you shouldn&#39;t rely on the broker&#39;s behaviour<br>
when publishing mandatory/immediate messages inside transactions, but I<br>
think there are any pitfalls doing this with rabbit.<br>
<br>
<br>
As you may have guessed by now, the scenario you described isn&#39;t handled<br>
very nicely by AMQP.  We&#39;re introducing publisher confirms to remedy<br>
this.  The code&#39;s on default now, and should be in the next release.<br>
The basic idea is that the broker sends a basic.ack back to the<br>
publisher when it&#39;s dealt with a message.  In addition, the basic.return<br>
would always be sent before the basic.ack, so the publisher would know<br>
when the message is no longer its responsibility.  Of course, this<br>
isn&#39;t synchronous, but it is fast, and the logic is a lot simpler than<br>
trying to do the same thing with transactions.<br>
<div><br>
<br>
&gt; PS: I&#39;m using the API version 1.7.2 and RabbitMQ server is the same version.<br>
<br>
</div>You really should upgrade.  Since 1.7.2, we&#39;ve fixed lots of bugs<br>
(including a few serious ones), introduced a new persister (which is<br>
quite relevant if you care about transfer of responsibility) and added some<br>
very nice management and monitoring features (including a web UI).<br>
Publisher confirms are on default now, and should be in the next<br>
release.<br>
<br>
<br>
Hope this helps,<br>
<br>
Cheers,<br>
Alex<br>
<div><div></div><div><br>
On Mon, Jan 24, 2011 at 05:47:17PM +0100, Alfonso Pantoja wrote:<br>
&gt; Hi,<br>
&gt;<br>
&gt; I&#39;ve developed an application that consumes messages from a queue (&quot;events<br>
&gt; queue&quot;) and depending on their data<br>
&gt; it publishes (per received message) a message to another queue (&quot;results<br>
&gt; queue&quot;)<br>
&gt;<br>
&gt; The logic that checks the content of the received messages is publishing<br>
&gt; messages using BasicPublish (with mandatory=2, immediate=false and setting<br>
&gt; deliveryMode=2 to the messages to be sent)<br>
&gt; My concern is that BasicPublish is asynchronous  and the only exception I<br>
&gt; can get is when there is no connection to RabbitMQ or the destination<br>
&gt; exchange does not exist.<br>
&gt;<br>
&gt; Since the application logic at this point is synchronous I can&#39;t use<br>
&gt; BasicReturn in order to use a handler when messages can&#39;t be delivered.<br>
&gt;<br>
&gt; I&#39;ve been googling a lot and some people suggested using this schema:<br>
&gt;<br>
&gt; ch.TxSelect()<br>
&gt; ch.BasicPublish(.....)<br>
&gt; ch.TxCommit()<br>
&gt;<br>
&gt; and also is suggested that &quot;commit-ok&quot; will be returned if the message has<br>
&gt; been published safely to the broker.<br>
&gt;<br>
&gt; Reading the API user guide I&#39;ve found that this is called &quot;transfer<br>
&gt; responsibility&quot;.<br>
&gt;<br>
&gt; Copy &amp; paste follows:<br>
&gt;<br>
&gt; --<br>
&gt; To transfer responsibility for delivery of a message to a broker<br>
&gt; • ensure (ahead of time) that the target queue exists and is durable,<br>
&gt; • select Tx mode using IModel.TxSelect,<br>
&gt; • publish the message with the &quot;mandatory&quot; flag set and DeliveryMode set<br>
&gt; equal to 2, and<br>
&gt; • commit the Tx transaction using IModel.TxCommit.<br>
&gt;<br>
&gt; Once a broker replies with CommitOk (i.e. the TxCommit() call returns to the<br>
&gt; caller), it has taken<br>
&gt; responsibility for keeping the message on disk and on the target queue until<br>
&gt; some other application<br>
&gt; retrieves and acknowledges the message.<br>
&gt; A commit is not required after every message: batching of publications may<br>
&gt; be done, depending on the<br>
&gt; precise delivery guarantees the publishing application requires.<br>
&gt; Responsibility can also be placed with an external database, even further<br>
&gt; along the chain - see the section<br>
&gt; on interaction with external resources below<br>
&gt; ---<br>
&gt;<br>
&gt; My question is:<br>
&gt;<br>
&gt; Being TxCommit a void function I tested this block of code using a<br>
&gt; non-existing routing key and I didn&#39;t get any exception.<br>
&gt; Since safe publishing would be highly desiderable non routed messages should<br>
&gt; be detected because the application ACKs the messages of &quot;events queue&quot;<br>
&gt; when after evaluating its content has successfully sent another message to<br>
&gt; the &quot;results queue&quot; (currently if a a routing key is not being routed to a<br>
&gt; queue the messages are silently dropped and I have no way to detect the<br>
&gt; failure so the application ACKs the messages from &quot;events queue&quot;)<br>
&gt;<br>
&gt; Please, can someone tell me how I can&#39;t get that &quot;CommitOK&quot; responses?<br>
&gt;<br>
&gt;<br>
&gt; Thank you in advance.<br>
&gt;<br>
&gt;<br>
&gt; Alfonso<br>
&gt;<br>
&gt; PS: I&#39;m using the API version 1.7.2 and RabbitMQ server is the same version.<br>
<br>
</div></div>&gt; _______________________________________________<br>
&gt; rabbitmq-discuss mailing list<br>
&gt; <a href="mailto:rabbitmq-discuss@lists.rabbitmq.com" target="_blank">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>
</blockquote></div><br></div>