gmr / rabbitpy

A pure python, thread-safe, minimalistic and pythonic RabbitMQ client library
http://rabbitpy.readthedocs.org
BSD 3-Clause "New" or "Revised" License
242 stars 58 forks source link

RabbitMQ connection does not throw exception while publishing a message when my RabbitMQ server is not running #128

Open NikunjVadodariya opened 3 years ago

NikunjVadodariya commented 3 years ago

I have created an app-level connection and an app-level channel, and I am using that connection&channel between multiple requests to publish a message.

My connection code:

        app.conn = rabbitpy.Connection('amqp://guest:guest@127.0.0.1:5672/%2f')
        app.channel = app.conn.channel()

My publisher code:

      message = rabbitpy.Message(app.channel, json.dumps({"test": "test"}))
      message.publish('test', 'test', mandatory=True)

I can not use channel.enable_publisher_confirms() because it takes more time when the load is high

When I shut down my RabbitMQ server then If I publish a message then It should throw an exception but it is not throwing, So how can I know that my message is published or not?

And in above sitiation If I use channel.enable_publisher_confirms() , then at that point my program goes in to infinity loop(dead lock) in the function message.publish('test', 'test', mandatory=True)

I am using python 3.5(flask app), rabbitpy 2.0.1

cmlara commented 3 years ago

You may want to glance at #119 as it is somewhat related. message.publish() without publisher confirms is "fire and forget" with no checks in it to know if the message was delivered or not.

Ultimately if you need to be sure the message is delivered you will need enable_publisher_confirms() (which is a call to the server so the server needs to be online for this function to complete successfully)

You may be able to connect the channel going down if the channel is used as contextmanager but that won't tell you for sure if a message was delivered or not.

NikunjVadodariya commented 3 years ago

@cmlara Thanks, You mean I have to use enable_publisher_confirms(), Right? But as I mentioned if I use enable_publisher_confirms() then at that point my program goes into infinity loop(dead lock) in the function message.publish('test', 'test', mandatory=True).

And It does not throw an exception, it is stuck there,. I need to restart my flask application.

cmlara commented 3 years ago

Yes to 100% know a message was not delivered you would need to have enable_publisher_confirms() on.

My apologies that I misread when the deadlock would occur in your sample code.

I did a quick test run from the command line (not in flask) with with the sample below (killing the rabbitserver during the sleep) and saw an exception raised both with and without publisher confirms enabled on the channel. I was not able to reproduce a deadlock. So at least it appears in non-complex situations the code is there to handle it.

I'm not a rabbitpy or flask expert, so at this point the best I can suggest is if you haven't already some debug logging may help to be sure if rabbitpy is seeing the shutdown or not and to help make sure there isn't some other part of the code that is perhaps interfering.

import logging, json, time
import rabbitpy

logging.basicConfig(level=logging.DEBUG)

conn = rabbitpy.Connection('amqp://guest:guest@127.0.0.1:5672/%2f')
channel = conn.channel()
channel.enable_publisher_confirms()
print("Just about to sleep. kill the rabbitmq-server now")
time.sleep(30)
message = rabbitpy.Message(channel, json.dumps({"test": "test"}))
print("about to publish")
message.publish('test', 'test', mandatory=True)
NikunjVadodariya commented 3 years ago

@cmlara Thanks for your effort, If the load is low then deadlock would occur. I fired 1000 request concurrently and stuck in the deadlock