|  | @@ -7,68 +7,6 @@ This module contains the component responsible for consuming messages
 | 
	
		
			
				|  |  |  from the broker, processing the messages and keeping the broker connections
 | 
	
		
			
				|  |  |  up and running.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* :meth:`~Consumer.start` is an infinite loop, which only iterates
 | 
	
		
			
				|  |  | -  again if the connection is lost. For each iteration (at start, or if the
 | 
	
		
			
				|  |  | -  connection is lost) it calls :meth:`~Consumer.reset_connection`,
 | 
	
		
			
				|  |  | -  and starts the consumer by calling :meth:`~Consumer.consume_messages`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* :meth:`~Consumer.reset_connection`, clears the internal queues,
 | 
	
		
			
				|  |  | -  establishes a new connection to the broker, sets up the task
 | 
	
		
			
				|  |  | -  consumer (+ QoS), and the broadcast remote control command consumer.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  Also if events are enabled it configures the event dispatcher and starts
 | 
	
		
			
				|  |  | -  up the heartbeat thread.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* Finally it can consume messages. :meth:`~Consumer.consume_messages`
 | 
	
		
			
				|  |  | -  is simply an infinite loop waiting for events on the AMQP channels.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  Both the task consumer and the broadcast consumer uses the same
 | 
	
		
			
				|  |  | -  callback: :meth:`~Consumer.receive_message`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* So for each message received the :meth:`~Consumer.receive_message`
 | 
	
		
			
				|  |  | -  method is called, this checks the payload of the message for either
 | 
	
		
			
				|  |  | -  a `task` key or a `control` key.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  If the message is a task, it verifies the validity of the message
 | 
	
		
			
				|  |  | -  converts it to a :class:`celery.worker.job.Request`, and sends
 | 
	
		
			
				|  |  | -  it to :meth:`~Consumer.on_task`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  If the message is a control command the message is passed to
 | 
	
		
			
				|  |  | -  :meth:`~Consumer.on_control`, which in turn dispatches
 | 
	
		
			
				|  |  | -  the control command using the control dispatcher.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  It also tries to handle malformed or invalid messages properly,
 | 
	
		
			
				|  |  | -  so the worker doesn't choke on them and die. Any invalid messages
 | 
	
		
			
				|  |  | -  are acknowledged immediately and logged, so the message is not resent
 | 
	
		
			
				|  |  | -  again, and again.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* If the task has an ETA/countdown, the task is moved to the `timer`
 | 
	
		
			
				|  |  | -  so the :class:`timer2.Timer` can schedule it at its
 | 
	
		
			
				|  |  | -  deadline. Tasks without an eta are moved immediately to the `ready_queue`,
 | 
	
		
			
				|  |  | -  so they can be picked up by the :class:`~celery.worker.mediator.Mediator`
 | 
	
		
			
				|  |  | -  to be sent to the pool.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* When a task with an ETA is received the QoS prefetch count is also
 | 
	
		
			
				|  |  | -  incremented, so another message can be reserved. When the ETA is met
 | 
	
		
			
				|  |  | -  the prefetch count is decremented again, though this cannot happen
 | 
	
		
			
				|  |  | -  immediately because amqplib doesn't support doing broker requests
 | 
	
		
			
				|  |  | -  across threads. Instead the current prefetch count is kept as a
 | 
	
		
			
				|  |  | -  shared counter, so as soon as  :meth:`~Consumer.consume_messages`
 | 
	
		
			
				|  |  | -  detects that the value has changed it will send out the actual
 | 
	
		
			
				|  |  | -  QoS event to the broker.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* Notice that when the connection is lost all internal queues are cleared
 | 
	
		
			
				|  |  | -  because we can no longer ack the messages reserved in memory.
 | 
	
		
			
				|  |  | -  However, this is not dangerous as the broker will resend them
 | 
	
		
			
				|  |  | -  to another worker when the channel is closed.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -* **WARNING**: :meth:`~Consumer.stop` does not close the connection!
 | 
	
		
			
				|  |  | -  This is because some pre-acked messages may be in processing,
 | 
	
		
			
				|  |  | -  and they need to be finished before the channel is closed.
 | 
	
		
			
				|  |  | -  For celeryd this means the pool must finish the tasks it has acked
 | 
	
		
			
				|  |  | -  early, *then* close the connection.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  """
 | 
	
		
			
				|  |  |  from __future__ import absolute_import
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -79,6 +17,7 @@ import threading
 | 
	
		
			
				|  |  |  from time import sleep
 | 
	
		
			
				|  |  |  from Queue import Empty
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +from kombu.common import QoS
 | 
	
		
			
				|  |  |  from kombu.syn import _detect_environment
 | 
	
		
			
				|  |  |  from kombu.utils.encoding import safe_repr
 | 
	
		
			
				|  |  |  from kombu.utils.eventio import READ, WRITE, ERR
 | 
	
	
		
			
				|  | @@ -101,9 +40,6 @@ from .heartbeat import Heart
 | 
	
		
			
				|  |  |  #: Heartbeat check is called every heartbeat_seconds' / rate'.
 | 
	
		
			
				|  |  |  AMQHEARTBEAT_RATE = 2.0
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#: Prefetch count can't exceed short.
 | 
	
		
			
				|  |  | -PREFETCH_COUNT_MAX = 0xFFFF
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  UNKNOWN_FORMAT = """\
 | 
	
		
			
				|  |  |  Received and deleted unknown message. Wrong destination?!?
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -198,63 +134,6 @@ class Component(StartStopComponent):
 | 
	
		
			
				|  |  |          return c
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -class QoS(object):
 | 
	
		
			
				|  |  | -    """Thread safe increment/decrement of a channels prefetch_count.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    :param consumer: A :class:`kombu.messaging.Consumer` instance.
 | 
	
		
			
				|  |  | -    :param initial_value: Initial prefetch count value.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    """
 | 
	
		
			
				|  |  | -    prev = None
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def __init__(self, consumer, initial_value):
 | 
	
		
			
				|  |  | -        self.consumer = consumer
 | 
	
		
			
				|  |  | -        self._mutex = threading.RLock()
 | 
	
		
			
				|  |  | -        self.value = initial_value or 0
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def increment_eventually(self, n=1):
 | 
	
		
			
				|  |  | -        """Increment the value, but do not update the channels QoS.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The MainThread will be responsible for calling :meth:`update`
 | 
	
		
			
				|  |  | -        when necessary.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        """
 | 
	
		
			
				|  |  | -        with self._mutex:
 | 
	
		
			
				|  |  | -            if self.value:
 | 
	
		
			
				|  |  | -                self.value = self.value + max(n, 0)
 | 
	
		
			
				|  |  | -        return self.value
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def decrement_eventually(self, n=1):
 | 
	
		
			
				|  |  | -        """Decrement the value, but do not update the channels QoS.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        The MainThread will be responsible for calling :meth:`update`
 | 
	
		
			
				|  |  | -        when necessary.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        """
 | 
	
		
			
				|  |  | -        with self._mutex:
 | 
	
		
			
				|  |  | -            if self.value:
 | 
	
		
			
				|  |  | -                self.value -= n
 | 
	
		
			
				|  |  | -        return self.value
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def set(self, pcount):
 | 
	
		
			
				|  |  | -        """Set channel prefetch_count setting."""
 | 
	
		
			
				|  |  | -        if pcount != self.prev:
 | 
	
		
			
				|  |  | -            new_value = pcount
 | 
	
		
			
				|  |  | -            if pcount > PREFETCH_COUNT_MAX:
 | 
	
		
			
				|  |  | -                warn('QoS: Disabled: prefetch_count exceeds %r',
 | 
	
		
			
				|  |  | -                     PREFETCH_COUNT_MAX)
 | 
	
		
			
				|  |  | -                new_value = 0
 | 
	
		
			
				|  |  | -            debug('basic.qos: prefetch_count->%s', new_value)
 | 
	
		
			
				|  |  | -            self.consumer.qos(prefetch_count=new_value)
 | 
	
		
			
				|  |  | -            self.prev = pcount
 | 
	
		
			
				|  |  | -        return pcount
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def update(self):
 | 
	
		
			
				|  |  | -        """Update prefetch count with current value."""
 | 
	
		
			
				|  |  | -        with self._mutex:
 | 
	
		
			
				|  |  | -            return self.set(self.value)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  class Consumer(object):
 | 
	
		
			
				|  |  |      """Listen for messages received from the broker and
 | 
	
		
			
				|  |  |      move them to the ready queue for task processing.
 |