Repository: celery/celery

Issue:
Broadcast messages in Celery 4.0.1 + Django not worked for me
## Checklist

- [x] I have included the output of ``celery -A proj report`` in the issue.
      (if you are not able to do this, then at least specify the Celery
       version affected).
- [x] I have verified that the issue exists against the `master` branch of Celery.

## Steps to reproduce
I'm using django 1.8 + Celery 4.0.1 + Kombu 4.0.1 + Redis as broker

from kombu.common import Broadcast
CELERY_QUEUE_BROADCAST = 'broadcast'
CELERY_QUEUES = (Broadcast(queue=CELERY_QUEUE_BROADCAST), )

@task(ignore_result=True, queue=CELERY_QUEUE_BROADCAST)
def broadcast_task():
    print "task runned"

started two workers
celery -A proj worker -Q broadcast

broadcast_task.delay() 
## Expected behavior
tasks are performed by each worker at same time
## Actual behavior
tasks performed by one worker at same time

also i placed my question on SO
http://stackoverflow.com/questions/41639334/broadcast-messages-in-celery-4-x



Discussion:
Duplicate celery/celery#3740?
Maybe. But it's bad. I hope my fault in incorrect settings. 

Resolving patch:
diff --git a/celery/app/amqp.py b/celery/app/amqp.py
--- a/celery/app/amqp.py
+++ b/celery/app/amqp.py
@@ -521,7 +521,7 @@ def send_task_message(producer, name, message,
                     exchange_type = 'direct'
 
             # convert to anon-exchange, when exchange not set and direct ex.
-            if not exchange or not routing_key and exchange_type == 'direct':
+            if (not exchange or not routing_key) and exchange_type == 'direct':
                     exchange, routing_key = '', qname
             elif exchange is None:
                 # not topic exchange, and exchange not undefined


Test patch:
diff --git a/t/unit/app/test_amqp.py b/t/unit/app/test_amqp.py
--- a/t/unit/app/test_amqp.py
+++ b/t/unit/app/test_amqp.py
@@ -264,6 +264,41 @@ def test_send_task_message__queue_string(self):
         assert kwargs['routing_key'] == 'foo'
         assert kwargs['exchange'] == ''
 
+    def test_send_task_message__broadcast_without_exchange(self):
+        from kombu.common import Broadcast
+        evd = Mock(name='evd')
+        self.app.amqp.send_task_message(
+            Mock(), 'foo', self.simple_message, retry=False,
+            routing_key='xyz', queue=Broadcast('abc'),
+            event_dispatcher=evd,
+        )
+        evd.publish.assert_called()
+        event = evd.publish.call_args[0][1]
+        assert event['routing_key'] == 'xyz'
+        assert event['exchange'] == 'abc'
+
+    def test_send_event_exchange_direct_with_exchange(self):
+        prod = Mock(name='prod')
+        self.app.amqp.send_task_message(
+            prod, 'foo', self.simple_message_no_sent_event, queue='bar',
+            retry=False, exchange_type='direct', exchange='xyz',
+        )
+        prod.publish.assert_called()
+        pub = prod.publish.call_args[1]
+        assert pub['routing_key'] == 'bar'
+        assert pub['exchange'] == ''
+
+    def test_send_event_exchange_direct_with_routing_key(self):
+        prod = Mock(name='prod')
+        self.app.amqp.send_task_message(
+            prod, 'foo', self.simple_message_no_sent_event, queue='bar',
+            retry=False, exchange_type='direct', routing_key='xyb',
+        )
+        prod.publish.assert_called()
+        pub = prod.publish.call_args[1]
+        assert pub['routing_key'] == 'bar'
+        assert pub['exchange'] == ''
+
     def test_send_event_exchange_string(self):
         evd = Mock(name='evd')
         self.app.amqp.send_task_message(