6

I have a very simple code:

celery = Celery(broker="amqp://guest:guest@172.17.0.1:5672/")                                                                                                                                                                                                           
celery.send_task(                                                                                                                                                                                                                            
    "robot.worker",                                                                                                                                                                                                                
    kwargs={},                                                                                                                                                                                                                               
    exchange="I_am_useless", # with  exchange=Exchange("I_am_useless") I got the same results                                                                                                                                                                                                          
)                                                                                                                                                                                                                                            

I really need the task to be sent to the exchange "I_am_useless", however it is not sent there, when I debug at the AMQP protocol level I see that a publish event is sent (which is ok) but with the following characteristic

reserved-1': 0,
'exchange-name': '',
'routing-key': 'celery',
'mandatory': False,
'immediate': False

so it seems the parameter is totally ignored, as even during the exchange declaration event, the name "celery" is used. but according to the documentation send_task takes the same parameters as https://docs.celeryproject.org/en/latest/reference/celery.app.task.html#celery.app.task.Task.apply_async , and we can see there's a "exchange" parameter that should accept a string.

however if I call kombu directly

rabbit_url = "amqp://guest:guest@172.17.0.1:5672/"                                                                                                                                                                                           
conn = Connection(rabbit_url)                                                                                                                                                                                                               
channel = conn.channel()                                                                                                                                                                                                                    
exchange = Exchange("example-exchange", type="direct")                                                                                                                                                                                      
producer = Producer(exchange=exchange, channel=channel, routing_key="BOB")                                                                                                                                                                  
queue = Queue(name="example-queue", exchange=exchange, routing_key="BOB")                                                                                                                                                                   
queue.maybe_bind(conn)                                                                                                                                                                                                                      
queue.declare()                                                                                                                                                                                                                             
producer.publish("Hello there!")                                                                                                                                                                                                            

I correctly see the exchange name, so I'm wondering what I'm doing wrong ?

allan.simon
  • 3,886
  • 6
  • 35
  • 60

1 Answers1

4

After looking into the code and a bit of experimenting, it seems that you need to also specify exchange_type and routing_key arguments when calling send_task.

Tomáš Linhart
  • 9,832
  • 1
  • 27
  • 39
  • thanks a lot ! I planned to do that as a last resort in case I got no answer but you did before me, so I think i will open a bug (documentation bug?) as it's at leat not clear from the documentation that it is the actual behaviour – allan.simon Sep 24 '19 at 17:23
  • You can find some clues in the [docs](https://docs.celeryproject.org/en/latest/userguide/routing.html#manual-routing), however I admit it's not explicit. – Tomáš Linhart Sep 25 '19 at 04:46
  • However what is interesting is that the code above does declare a "celery" exchange of type direct, but then does not use it. I need to dig in the AMQP/Rabbitmq sepc, because right now it's causing a bug as I'm using a custom implementation of the AMQP protocol, where the anonymous exchange does not exists (so the message can not be published, so i need to check if it's a bug in my amqp implementation or an undocumented feature of rabbitmq) – allan.simon Sep 25 '19 at 06:01
  • ok I understand better AMQP0.9.1 does define a default exchange "empty string" that is bound to all queue. (which my custom implementation was not doing) so celery with the code above, is defining a exchange "celery" , a queue celery (with a routing key "celery") that is by bound on rabbitmq side to exchange "", so the publish above was working because the message was published to that default exchange, so still arriving to the correct queue, even though not through the exchange declared by the code. (I'm going to edit your answer with your permissions to add these precision ?) – allan.simon Sep 25 '19 at 07:22
  • Feel free to edit the answer to better explain what's going on internally. – Tomáš Linhart Sep 25 '19 at 07:34