Beispiel #1
0
    def __setup_rackhd_style_amqp(self):
        """
        Need to make exchanges and named queus to make this
        look like a RackHD instance amqp.
        """
        # A freshly spun up on-demand docker likes to say it's there, but will
        # then reset the connection. So, catch that scenario w/ a few retries.
        con = None
        done_time = time.time() + 30.0
        while con is None:
            con = Connection(hostname=self.host, port=self.ssl_port, ssl=False)
            try:
                con.connect()
            except Exception as ex:
                if time.time() > done_time:
                    raise ex
                con = None
            if con is None:
                time.sleep(0.1)

        on_task = self.__assure_exchange(con, 'on.task', 'topic')
        self.__assure_named_queue(con, on_task, 'ipmi.command.sel.result')
        self.__assure_named_queue(con, on_task, 'ipmi.command.sdr.result')
        self.__assure_named_queue(con, on_task, 'ipmi.command.chassis.result')

        on_events = self.__assure_exchange(con, 'on.events', 'topic')
        self.__assure_named_queue(con, on_events, 'graph.finished')
        self.__assure_named_queue(con, on_events, 'polleralert.sel.updated',
                                  '#')
Beispiel #2
0
def init_adversary():
    global __username, __my_type, __connection, __global_exchange, __producer, __backchannel, __backch_producer, __adv_exchange, __adv_queue  #, __my_queue

    __username = '******'
    __my_type = 'adversary'

    #adversary has broadcast-only access to the regular exchange
    __connection = Connection('amqp://')
    __connection.connect()
    __global_exchange = Exchange('broadcast',
                                 type='fanout',
                                 durable=False,
                                 delivery_mode=1)
    __global_exchange.maybe_bind(__connection)
    __producer = __connection.Producer(__connection)

    __backchannel = Connection('amqp://')
    __backchannel.connect()
    __adv_exchange = Exchange('adversary', durable=False, delivery_mode=1)
    __adv_exchange.maybe_bind(__backchannel)
    __backch_producer = __backchannel.Producer(__backchannel)
    __adv_queue = Queue('adversary',
                        exchange=__adv_exchange,
                        routing_key='adversary',
                        durable=False)
    __adv_queue = __adv_queue(__backchannel)
    __adv_queue.declare()
Beispiel #3
0
    def _connect(self):

        result = None

        if not self.connected():

            self.logger.info(
                "Connect to RabbitMQ Broker %s" % (self.uri))

            uri = self.uri

            parsed_url = urlparse(uri)

            uri = 'amqp://%s/%s' % (parsed_url.netloc, parsed_url.path)

            result = Connection(uri)

            try:
                result.connect()
                self.logger.info("Connected to AMQP Broker.")

            except Exception as e:
                result.release()
                self.logger.error(
                    "Connection failure to %s: %s" % (uri, e))

        else:
            self.logger.debug("Allready connected")

        return result
Beispiel #4
0
    def __setup_rackhd_style_amqp(self):
        """
        Need to make exchanges and named queus to make this
        look like a RackHD instance amqp.
        """
        # A freshly spun up on-demand docker likes to say it's there, but will
        # then reset the connection. So, catch that scenario w/ a few retries.
        con = None
        done_time = time.time() + 30.0
        while con is None:
            con = Connection(hostname=self.host, port=self.ssl_port, ssl=False)
            try:
                con.connect()
            except Exception as ex:
                if time.time() > done_time:
                    raise ex
                con = None
            if con is None:
                time.sleep(0.1)

        on_task = self.__assure_exchange(con, 'on.task', 'topic')
        self.__assure_named_queue(con, on_task, 'ipmi.command.sel.result')
        self.__assure_named_queue(con, on_task, 'ipmi.command.sdr.result')
        self.__assure_named_queue(con, on_task, 'ipmi.command.chassis.result')

        on_events = self.__assure_exchange(con, 'on.events', 'topic')
        self.__assure_named_queue(con, on_events, 'graph.finished')
        self.__assure_named_queue(con, on_events, 'polleralert.sel.updated', '#')
Beispiel #5
0
class AmqpBundle(object):

    def __init__(self):
        self.logger = logging.getLogger("amqp_bundle")
        self.config_mapping = {
            "amqp": {
                "uri": None,
                "autodisconnect": False,
                "heartbeat": 0,
            }
        }
        self.autodisconnect = None

        self.event_listeners = [
            (ConfigurationReadyEvent, self.configuration_ready),
            (KernelShutdownEvent, self.kernel_shutdown),
        ]

        self.connection = Connection()
        self.injection_bindings = {Connection: self.connection}

    def kernel_shutdown(self, event):
        if self.autodisconnect:
            self.logger.info("Disconnecting...")
            self.connection.release()
            self.logger.info("Disconnected")

    def configuration_ready(self, event):
        c = event.configuration.amqp
        self.autodisconnect = c.autodisconnect
        # First connect the topic manager to avoid lose messages
        self.connection.__init__(c.uri, heartbeat=c.heartbeat)
        self.connection.connect()
        self.logger.info("Connected")
class KombuSocket(object):
    def __init__(self, host, port, username, password, virtual_host, exchange,
                 routing_key, durable, passive, exchange_type):
        # create connection
        self.connection = Connection(hostname=host,
                                     port=port,
                                     userid=username,
                                     password=password,
                                     virtual_host=virtual_host)

        # create exchange
        self.exchange = Exchange(exchange, type=exchange_type, durable=durable)
        self.exchange.passive = passive

        # other publishing params
        self.routing_key = routing_key

    def sendall(self, data):
        with producers[self.connection].acquire(block=True) as producer:
            producer.publish(data,
                             routing_key=self.routing_key,
                             exchange=self.exchange,
                             declare=[self.exchange])

    def connect(self):
        self.connection.connect()

    def close(self):
        try:
            self.connection.close()
        except Exception:
            pass
Beispiel #7
0
def run(rabbit_url):
    print rabbit_url
    conn = Connection(rabbit_url)
    conn.ensure_connection()
    conn.connect()
    channel = conn.channel()
    exchange = Exchange(config.EXCHANGE_NAME, type='direct')

    producer = Producer(exchange=exchange,
                        channel=channel,
                        routing_key=config.ROUTING_KEY)

    queue = Queue(name=config.QUEUE_NAME,
                  exchange=exchange,
                  routing_key=config.ROUTING_KEY)
    queue.maybe_bind(conn)
    queue.declare()

    index = 0
    while True:
        try:
            time.sleep(1)
            print 'producer'
            index += 1
            producer.publish("send message -- %s" % index)
        except socket.timeout:
            pass
Beispiel #8
0
 def test_missing_master_name_transport_option(self):
     connection = Connection('sentinel://localhost:65534/', )
     with patch('redis.sentinel.Sentinel'),  \
          pytest.raises(ValueError) as excinfo:
         connection.connect()
     expected = "'master_name' transport option must be specified."
     assert expected == excinfo.value.args[0]
Beispiel #9
0
class RabbitMQPublisher(object):

    def __init__(self, source_id, network_id, model_key=None, run_key=None):
        broker_url = get_broker_url(model_key)
        self.conn = Connection(broker_url)
        self.conn.connect()

        self.channel = 'oa-{source_id}-{network_id}-{model_key}'.format(
            source_id=source_id,
            network_id=network_id,
            model_key=model_key or environ.get(constants.MODEL_KEY)
        )
        if run_key is not None:
            self.channel += '-{}'.format(run_key)

        self.producer = self.conn.Producer(serializer='json')

        # set up the Exchange, Queue, and Producer
        media_exchange = Exchange('media', 'direct', durable=True)
        video_queue = Queue('video', exchange=media_exchange, routing_key='video')


    # publish updates
    def publish(self, payload):
        self.producer.publish(self.channel, json.dumps(payload))

    def close(self):
        self.conn.release()
Beispiel #10
0
class Test(unittest.TestCase):
    def setUp(self):
        self.__conn = Connection(transport=Transport)
        self.__conn.connect()
        self.__exchange = Exchange('test_exchange')
        self.__routing_key = 'test.routing'
        self.__queue = Queue('test_queue',
                             self.__exchange,
                             routing_key=self.__routing_key)

    def test_register_player(self):
        message, exchange, routing_key = register_player(
            111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_FIND_PLAYER,
                         body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_pgpool_disconnected(self):
        message, exchange, routing_key = acknowledgement_pgpool_disconnected(
            111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_DISCONNECT_PGPOOL,
                         body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_pgpool_connected(self):
        message, exchange, routing_key = acknowledgement_pgpool_connected(
            111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_CONNECT_PGPOOL,
                         body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_master_disconnected(self):
        message, exchange, routing_key = acknowledgement_master_disconnected(
            111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_STOP_REPLICATION,
                         body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_master_connected(self):
        message, exchange, routing_key = acknowledgement_master_connected(
            111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_START_REPLICATION,
                         body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)
Beispiel #11
0
    def inner(*args, **kwargs):
        connection = Connection(settings.BROKER_URL)
        connection.connect()

        queue = connection.SimpleQueue(settings.QUEUE_NAME)
        res = func(*args, **kwargs, queue=queue)
        connection.release()
        return res
Beispiel #12
0
 def test_simple_queueing(self):
     conn = Connection('sqlalchemy+sqlite:///:memory:')
     conn.connect()
     channel = conn.channel()
     self.assertEqual(channel.queue_cls.__table__.name, 'kombu_queue')
     self.assertEqual(channel.message_cls.__table__.name, 'kombu_message')
     channel._put('celery', 'DATA')
     assert channel._get('celery') == 'DATA'
Beispiel #13
0
def test_amqp_connect(config):
    connect_url = 'amqp://{user}:{pwd}@{host}:{port}//' \
        .format(user=config.get("user", ''),
                pwd=config.get('pwd', ''),
                host=config.get('host', ''),
                port=int(config.get('port', 5671)))
    conn = Connection(connect_url)
    conn.connect()
Beispiel #14
0
class _AMQPServerWrapper(object):
    def __init__(self, amqp_url, logs):
        self.__logs = logs
        self.__amqp_url = amqp_url
        self.__monitors = {}
        self.__connection = Connection(self.__amqp_url)
        self.__connection.connect()
        self.__running = True
        self.__consumer_gl = gevent.spawn(self.__consumer_greenlet_main)
        self.__consumer_gl.greenlet_name = 'amqp-consumer-gl'  # allowing flogging to print a nice name
        gevent.sleep(0.0)

    def __consumer_greenlet_main(self):
        gevent.sleep(0)
        while self.__running:
            try:
                self.__connection.drain_events(timeout=0.5)
            except Exception as ex:     # NOQA: assigned but not used (left in for super-duper-low-level-debug)
                # print("was woken because {}".format(ex))
                pass
            gevent.sleep(0.1)  # make -sure- to yield cpu...
            # print("---loop")

    def stop_greenlet(self):
        self.__running = False

    @property
    def connected(self):
        return self.__connection.connected

    def create_add_tracker(self, exchange, routing_key, event_cb, queue_name=None):
        self.__logs.irl.debug("AMQPServerWrapper: create_add_tracker ex=%s, rk=%s, event_cb=%s",
                              exchange, routing_key, event_cb)
        mon = _KeyedConsumerHandler.get_keyed_consumer(
            self.__logs, self.__connection, exchange, routing_key, queue_name, event_cb)
        return mon.exchange

    def inject(self, exchange, routing_key, payload):
        self.__logs.irl.debug("Injecting a test AMQP message: ex=%s, rk=%s, payload=%s", exchange, routing_key, payload)
        if not isinstance(exchange, Exchange):
            exchange = Exchange(exchange, 'topic')
        prod = Producer(self.__connection, exchange=exchange, routing_key=routing_key)
        prod.publish(payload)

    def test_helper_sync_send_msg(self, exchange, ex_rk, send_rk, payload):
        ex = Exchange(exchange, 'topic')
        queue = Queue(exchange=ex, routing_key=ex_rk + '.*', exclusive=True, channel=self.__connection)
        queue.declare()
        prod = Producer(self.__connection, exchange=ex, routing_key=send_rk)
        prod.publish(payload)
        return queue

    def test_helper_sync_recv_msg(self, queue):
        for tick in range(10):
            msg = queue.get()
            if msg is not None:
                break
        return msg
def health_check_rabbitmq(broker_url):
    try:
        from kombu import Connection
        conn = Connection(broker_url)
        conn.connect()
        conn.release()
        return True, 'Rabbitmq is OK.', ''
    except Exception as e:
        return False, str(e), traceback.format_exc()
Beispiel #16
0
class InteractiveExchange:
    '''
    A context manager that provides the interactive exchange for publishing 
    messages.
    '''
    def __init__(self, task):
        '''
        Accessing an Interactive Exchange need a task only for the generic info in it, 
        and so this can be an instantiaton of Interactive()
        
        :param task: A task that provides the exchange name and some logging formatters
        '''
        self.task = task

    def __enter__(self):
        # We have a task that we need only for the exchnage name and some logging formatters.
        task = self.task

        log.debug(f'Connecting to: {current_app.conf.broker_url}')

        self.connection = Connection(current_app.conf.broker_url)

        # Connection is lazy. Force a connection now.
        self.connection.connect()

        # Get the connection object for channel construction
        #
        # This syntax is odd, but we can blame kombu for that.
        #
        # self.connection is of type: kombu.connection.Connection
        #
        # and it has an attribute:
        #
        # self.connection.connection which is of type: kombu.transport.pyamqp.Connection
        #
        # So sname names, different things. The convoluted life of the
        # word "connection". But we do need a kombu.transport.pyamqp.Connection
        # object to create a channel. We can't do that on its parent.
        c = self.connection.connection
        log.debug(f'\tConnection: {task.connection_names(c)[1]}')

        # Create a channel on the connection and log it in the RabbitMQ webmonitor format
        ch = c.channel()
        self.channel = ch
        log.debug(f'\tChannel: {task.channel_names(ch)[1]}')

        x = Exchange(task.exchange_name, channel=ch)
        self.exchange = x
        log.debug(f'\tExchange: {x.name}')

        return x

    def __exit__(self, type, value, traceback):  # @ReservedAssignment
        self.connection.release()
Beispiel #17
0
    def test_simple_queueing(self):
        conn = Connection('sqlalchemy+sqlite:///:memory:')
        conn.connect()
        try:
            channel = conn.channel()
            assert channel.queue_cls.__table__.name == 'kombu_queue'
            assert channel.message_cls.__table__.name == 'kombu_message'

            channel._put('celery', 'DATA_SIMPLE_QUEUEING')
            assert channel._get('celery') == 'DATA_SIMPLE_QUEUEING'
        finally:
            conn.release()
class CeleryQueue(QueueBase):
    """ At some point this will adapt `django-signalqueue` for use
        with popular `(dj)celery` platform (but not today).
        
        When this class is done, I will discuss it here. """
    
    def __init__(self, *args, **kwargs):
        super(CeleryQueue, self).__init__(*args, **kwargs)
        
        self.celery_queue_name = self.queue_options.pop('celery_queue_name', 'inactive')
        self.serializer = self.queue_options.pop('serializer', 'json')
        self.compression = self.queue_options.pop('compression', None)
        self.kc = Connection(**self.queue_options)
        self.kc.connect()
        
        self.qc = self.kc.SimpleQueue(name=self.celery_queue_name)
    
    def ping(self):
        return self.kc.connected and not self.qc.channel.closed
    
    def push(self, value):
        self.qc.put(value,
            compression=self.compression, serializer=None)
    
    def pop(self):
        virtual_message = self.qc.get(block=False, timeout=1)
        return virtual_message.payload
    
    def count(self):
        try:
            return self.qc.qsize()
        except kombu.exceptions.StdChannelError:
            self.qc.queue.declare()
            return 0
    
    def clear(self):
        self.qc.clear()
    
    def values(self, **kwargs):
        return []
    
    def __getitem__(self, idx):
        #return self.values().__getitem__(idx)
        return ''
    
    def dispatch(self, signal, sender=None, **kwargs):
        task_name = "%s:%s" % (signal.regkey, signal.name)
        try:
            result = tasks[task_name].delay(sender=sender, **kwargs)
        except tasks.NotRegistered:
            pass
        else:
            return result
class CeleryQueue(QueueBase):
    """ At some point this will adapt `django-signalqueue` for use
        with popular `(dj)celery` platform (but not today).
        
        When this class is done, I will discuss it here. """
    def __init__(self, *args, **kwargs):
        super(CeleryQueue, self).__init__(*args, **kwargs)

        self.celery_queue_name = self.queue_options.pop(
            'celery_queue_name', 'inactive')
        self.serializer = self.queue_options.pop('serializer', 'json')
        self.compression = self.queue_options.pop('compression', None)
        self.kc = Connection(**self.queue_options)
        self.kc.connect()

        self.qc = self.kc.SimpleQueue(name=self.celery_queue_name)

    def ping(self):
        return self.kc.connected and not self.qc.channel.closed

    def push(self, value):
        self.qc.put(value, compression=self.compression, serializer=None)

    def pop(self):
        virtual_message = self.qc.get(block=False, timeout=1)
        return virtual_message.payload

    def count(self):
        try:
            return self.qc.qsize()
        except kombu.exceptions.StdChannelError:
            self.qc.queue.declare()
            return 0

    def clear(self):
        self.qc.clear()

    def values(self, **kwargs):
        return []

    def __getitem__(self, idx):
        #return self.values().__getitem__(idx)
        return ''

    def dispatch(self, signal, sender=None, **kwargs):
        task_name = "%s:%s" % (signal.regkey, signal.name)
        try:
            result = tasks[task_name].delay(sender=sender, **kwargs)
        except tasks.NotRegistered:
            pass
        else:
            return result
Beispiel #20
0
 def test_custom_table_names(self):
     conn = Connection('sqlalchemy+sqlite:///:memory:',
                       transport_options={
                           'queue_tablename': 'my_custom_queue',
                           'message_tablename': 'my_custom_message'
                       })
     conn.connect()
     channel = conn.channel()
     self.assertEqual(channel.queue_cls.__table__.name, 'my_custom_queue')
     self.assertEqual(channel.message_cls.__table__.name,
                      'my_custom_message')
     channel._put('celery', 'DATA')
     assert channel._get('celery') == 'DATA'
Beispiel #21
0
class Publisher(object):
    def __init__(self, connection_string, exchange, is_active=True):
        self._is_active = is_active
        self.is_connected = True
        if not is_active:
            self.is_connected = False
            return

        self._connection = Connection(connection_string)
        self._connections = set([self._connection])  # set of connection for the heartbeat
        self._exchange = Exchange(exchange, durable=True, delivry_mode=2, type='topic')
        self._connection.connect()
        monitor_heartbeats(self._connections)

    def _get_producer(self):
        producer = producers[self._connection].acquire(block=True, timeout=2)
        self._connections.add(producer.connection)
        return producer

    def publish(self, item, contributor):
        if not self._is_active:
            logging.getLogger(__name__).info('RabbitMQ is not enabled')
            return True

        with self._get_producer() as producer:
            try:
                self.is_connected = True
                publish = producer.connection.ensure(producer, producer.publish, max_retries=3)
                publish(item, exchange=self._exchange, routing_key=contributor, declare=[self._exchange])
                logging.getLogger(__name__).info('Publishing message on exchange %s', self._exchange.name)
            except:
                self.is_connected = False
                logging.exception("Impossible to publish message to rabbitmq")
            finally:
                return self.is_connected

    def info(self):
        result = {
            "is_active": self._is_active,
            "is_connected": self.is_connected
        }
        if not self._is_active:
            return result

        with self._get_producer() as producer:
            res = producer.connection.info()
            if 'password' in res:
                del res['password']
            for key, value in res.items():
                result[key] = value
        return result
Beispiel #22
0
    def test_close_survives_connerror(self):
        class _CustomError(Exception):
            pass

        class MyTransport(Transport):
            connection_errors = (_CustomError, )

            def close_connection(self, connection):
                raise _CustomError('foo')

        conn = Connection(transport=MyTransport)
        conn.connect()
        conn.close()
        self.assertTrue(conn._closed)
Beispiel #23
0
    def test_close_survives_connerror(self):
        class _CustomError(Exception):
            pass

        class MyTransport(Transport):
            connection_errors = (_CustomError,)

            def close_connection(self, connection):
                raise _CustomError("foo")

        conn = Connection(transport=MyTransport)
        conn.connect()
        conn.close()
        self.assertTrue(conn._closed)
Beispiel #24
0
 def test_simple_queueing(self):
     conn = Connection('sqlalchemy+sqlite:///:memory:')
     conn.connect()
     channel = conn.channel()
     self.assertEqual(
         channel.queue_cls.__table__.name,
         'kombu_queue'
     )
     self.assertEqual(
         channel.message_cls.__table__.name,
         'kombu_message'
     )
     channel._put('celery', 'DATA')
     assert channel._get('celery') == 'DATA'
Beispiel #25
0
def connect_to_amqp(sysconfig):
    """
    Connect to an AMQP Server, and return the connection and Exchange.
    :param sysconfig: The slickqaweb.model.systemConfiguration.amqpSystemConfiguration.AMQPSystemConfiguration instance
                      to use as the source of information of how to connect.
    :return: (connection, exchange) on success, exception on error
    """
    assert isinstance(sysconfig, AMQPSystemConfiguration)
    configuration = dict()
    configuration['AMQP'] = dict()
    if hasattr(sysconfig, 'hostname') and sysconfig.hostname is not None:
        configuration['AMQP']['hostname'] = sysconfig.hostname
    else:
        raise AMQPConnectionError(message="No hostname defined for AMQP connection.")
    if hasattr(sysconfig, 'port') and sysconfig.port is not None:
        configuration['AMQP']['port'] = sysconfig.port
    if hasattr(sysconfig, 'username') and sysconfig.username is not None:
        configuration['AMQP']['username'] = sysconfig.username
    if hasattr(sysconfig, 'password') and sysconfig.password is not None:
        configuration['AMQP']['password'] = sysconfig.password
    if hasattr(sysconfig, 'virtualHost') and sysconfig.virtualHost is not None:
        configuration['AMQP']['virtual host'] = sysconfig.virtualHost
    if hasattr(sysconfig, 'exchangeName') and sysconfig.exchangeName is not None:
        configuration['AMQP']['exchange'] = sysconfig.exchangeName
    else:
        raise AMQPConnectionError(message="No exchange defined for AMQP connection.")

    logger = logging.getLogger("slickqaweb.amqpcon.connect_to_amqp")

    url = str.format("amqp://{hostname}:{port}", **dict(list(configuration['AMQP'].items())))
    if 'virtual host' in configuration['AMQP'] and configuration['AMQP']['virtual host'] != '':
        url = str.format("{}/{}", url, configuration['AMQP']['virtual host'])
    logger.debug("AMQPConnection configured with url %s", url)
    exchange = Exchange(configuration['AMQP'].get('exchange', "amqp.topic"), type='topic', durable=True)
    logger.debug("AMQPConnection is using exchange %s", exchange)
    connection = None
    if 'username' in configuration['AMQP'] and 'password' in configuration['AMQP']:
        username = configuration['AMQP']['username']
        password = configuration['AMQP']['password']
        logger.debug("Using username %s and password %s to connect to AMQP Broker", username, password)
        connection = Connection(url, userid=username, password=password)
    else:
        connection = Connection(url)

    # typically connection connect on demand, but we want to flush out errors before proceeding
    connection.connect()
    exchange = exchange(connection)
    exchange.declare()
    return (connection, exchange)
Beispiel #26
0
def check_rabbit_mq():
    conn = Connection(settings.AMQP_URL)
    for attempt in range(1, 11):
        timeout = attempt * 2
        try:
            conn.connect()
            # Check connection
            conn.release()
            return True
        except OSError as e:
            logging.warning(
                "Cannot connect to AMQP at {}. Retrying in {} secs...".format(
                    settings.AMQP_URL, timeout))
            time.sleep(timeout)
    return False
class Test(unittest.TestCase):

    def setUp(self):
        self.__conn = Connection(transport=Transport)
        self.__conn.connect()
        self.__exchange = Exchange('test_exchange')
        self.__routing_key = 'test.routing'
        self.__queue = Queue('test_queue', self.__exchange, routing_key=self.__routing_key)

    def test_register_player(self):
        message, exchange, routing_key = register_player(111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_FIND_PLAYER, body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_pgpool_disconnected(self):
        message, exchange, routing_key = acknowledgement_pgpool_disconnected(111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_DISCONNECT_PGPOOL, body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_pgpool_connected(self):
        message, exchange, routing_key = acknowledgement_pgpool_connected(111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_CONNECT_PGPOOL, body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_master_disconnected(self):
        message, exchange, routing_key = acknowledgement_master_disconnected(111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_STOP_REPLICATION, body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)

    def test_acknowledgement_master_connected(self):
        message, exchange, routing_key = acknowledgement_master_connected(111, self.__conn, self.__exchange, self.__routing_key)
        body = json.loads(message['body'])
        self.assertEqual(Constants.ACK_COMMAND_START_REPLICATION, body[Constants.MESSAGE_ACK_COMMAND])
        self.assertEqual(111, body[Constants.MESSAGE_NODE_ID])
        self.assertEqual(self.__exchange.name, exchange)
        self.assertEqual(self.__routing_key, routing_key)
Beispiel #28
0
class Publisher(object):
    def __init__(self, connection_string, exchange, is_active=True):
        self._is_active = is_active
        self.is_connected = True
        if not is_active:
            self.is_connected = False
            return

        self._connection = Connection(connection_string)
        self._connections = set([self._connection])#set of connection for the heartbeat
        self._exchange = Exchange(exchange, durable=True, delivry_mode=2, type='topic')
        self._connection.connect()
        monitor_heartbeats(self._connections)

    def _get_producer(self):
        producer = producers[self._connection].acquire(block=True, timeout=2)
        self._connections.add(producer.connection)
        return producer

    def publish(self, item, contributor):
        if not self._is_active:
            return

        with self._get_producer() as producer:
            try:
                publish = producer.connection.ensure(producer, producer.publish, max_retries=3)
                publish(item, exchange=self._exchange, routing_key=contributor, declare=[self._exchange])
                self.is_connected = True
            except socket.error:
                self.is_connected = False
                logging.getLogger(__name__).debug('Impossible to publish message !')
                raise

    def info(self):
        result = {
            "is_active": self._is_active,
            "is_connected": self.is_connected
        }
        if not self._is_active:
            return result

        with self._get_producer() as producer:
            res = producer.connection.info()
            if 'password' in res:
                del res['password']
            for key, value in res.items():
                result[key] = value
        return result
Beispiel #29
0
def consumer_from_queue():
    connection = Connection(settings.BROKER_URL, heartbeat=5)
    connection.connect()

    exchange = Exchange(ADDRESS_EXCHANGE, type='direct')

    queue = Queue(
        name=ADDRESS_CUSTOMER_CONSUMER_QUEUE,
        routing_key=ADDRESS_ROUTING_KEY,
        exchange=exchange,
    )

    def process_message(body, message):
        logger.info('Message arrived with the following body {}'.format(body))
        get_longitude_latitude(body)
        message.ack()

    consumer = Consumer(connection, queues=queue, callbacks=[process_message], accept=['json', 'pickle', 'msgpack'])
    consumer.consume()

    def establish_connection():
        revived_connection = connection.clone()
        revived_connection.ensure_connection(max_retries=3)
        channel = revived_connection.channel()
        consumer.revive(channel)
        consumer.consume()
        return revived_connection

    def consume():
        new_connection = establish_connection()
        while True:
            try:
                new_connection.drain_events(timeout=2)
            except socket.timeout:
                new_connection.heartbeat_check()

    def run():
        logger.info('Starting consumer from address queue')
        while True:
            try:
                consume()
            except connection.connection_errors:
                logger.error('Something went wrong')
            finally:
                connection.close()

    run()
Beispiel #30
0
 def test_custom_table_names(self):
     conn = Connection('sqlalchemy+sqlite:///:memory:', transport_options={
         'queue_tablename': 'my_custom_queue',
         'message_tablename': 'my_custom_message'
     })
     conn.connect()
     channel = conn.channel()
     self.assertEqual(
         channel.queue_cls.__table__.name,
         'my_custom_queue'
     )
     self.assertEqual(
         channel.message_cls.__table__.name,
         'my_custom_message'
     )
     channel._put('celery', 'DATA')
     assert channel._get('celery') == 'DATA'
Beispiel #31
0
class Publisher(object):
    def __init__(self, connection_string, exchange, is_active=True):
        self._is_active = is_active
        self.is_connected = True
        if not is_active:
            self.is_connected = False
            return

        self._connection = Connection(connection_string)
        self._connections = set([self._connection
                                 ])  # set of connection for the heartbeat
        self._exchange = Exchange(exchange,
                                  durable=True,
                                  delivry_mode=2,
                                  type='topic')
        self._connection.connect()
        monitor_heartbeats(self._connections)

    def _get_producer(self):
        producer = producers[self._connection].acquire(block=True, timeout=2)
        self._connections.add(producer.connection)
        return producer

    def publish(self, item, contributor):
        if not self._is_active:
            logging.getLogger(__name__).info('RabbitMQ is not enabled')
            return True

        with self._get_producer() as producer:
            try:
                self.is_connected = True
                publish = producer.connection.ensure(producer,
                                                     producer.publish,
                                                     max_retries=3)
                publish(item,
                        exchange=self._exchange,
                        routing_key=contributor,
                        declare=[self._exchange])
                logging.getLogger(__name__).info(
                    'Publishing message on exchange %s', self._exchange.name)
            except BaseException, e:
                self.is_connected = False
                logging.exception("Impossible to publish message to rabbitmq")
                logging.exception(repr(e))
            finally:
Beispiel #32
0
 def handle(self, command):
     command_body = {
         "command": command.command,
         "argument": command.argument,
         "user_id": command.user_id,
         "chatroom_id": command.chatroom_id,
     }
     connection = Connection(settings.AMQP_ADDRESS)
     connection.connect()
     producer = connection.Producer()
     producer.publish(
         command_body,
         retry=True,
         exchange=settings.EXCHANGE,
         routing_key=settings.SENDER_ROUTING_KEY,
         declare=[settings.BOT_QUEUE],
     )
     connection.release()
Beispiel #33
0
    def check_rabbit_connections(self):
        if not self._controllers:
            self.fail('There are no online controllers')
        pwd = self.get_conf_values().strip()
        for host in self._controllers:
            try:
                conn = Connection(host, userid='nova',
                                  password=pwd,
                                  virtual_host='/', port=5673)
                conn.connect()

                channel = conn.channel()
                self.connections.append((channel, host))
                LOG.debug('connections is {0}'.format(self.connections))
            except Exception:
                LOG.debug(traceback.format_exc())
                self.fail("Failed to connect to "
                          "5673 port on host {0}".format(host))
Beispiel #34
0
def test_rabbitmq_on_startup(retry: int = 3, wait: float = 10):
    """
    Tests connection to RabbitMQ on application start up.
    :param retry: amount of connection retries
    :param wait: seconds to wait until connection retry
    """
    logging.info("Trying to connect to RabbitMQ ...")
    rabbitmq_connection = Kombu(rabbitmq_url)
    for i in range(0, retry):
        try:
            rabbitmq_connection.connect()
            logging.info("Successfully connected to RabbitMQ!")
            rabbitmq_connection.release()
            return True
        except KombuConnectionError or ConnectionRefusedError:
            logging.warning("RabbitMQ is not yet ready!")
            time.sleep(wait)
    raise Exception("Cannot connect to RabbitMQ!")
class SocketBrokerClient:
    """
    Base class for web socket notification using broker (redis or rabbitmq)
    """

    connection = None

    def __init__(self, url, exchange_name=None):
        self.url = url
        self.connect()
        self.exchange_name = exchange_name if exchange_name else celery_queue(
            "socket_notification")
        self.channel = self.connection.channel()
        self.socket_exchange = Exchange(self.exchange_name,
                                        type="fanout",
                                        channel=self.channel)
        self.socket_exchange.declare()

    def open(self):
        """Test if connection is open.

        True if connected else false

        :return bool:
        """
        return self.connection and self.connection.connected

    def connect(self):
        self._close()
        logger.info("Connecting to broker {}".format(self.url))
        self.connection = Connection(self.url, heartbeat=WS_HEART_BEAT)
        self.connection.connect()
        logger.info("Connected to broker {}".format(self.url))

    def _close(self):
        if hasattr(self, "connection") and self.connection:
            logger.info("Closing connecting to broker {}".format(self.url))
            self.connection.release()
            self.connection = None
            logger.info("Connection closed to broker {}".format(self.url))

    def close(self):
        self._close()
Beispiel #36
0
 def __call__(self):
     """
     Broker URL must start with "amqp://" else return None
     Return True if can establish connection or not.
     """
     if self.broker_url.startswith("amqp://"):
         try:
             connection = Connection(self.broker_url, connection_timeout=1)
             try:
                 connection.connect()
                 status = connection.connected
             finally:
                 connection.release()
         except Exception as exc:
             logger.exception(exc)
             status = False
         return status
     else:
         return None
Beispiel #37
0
class SocketBrokerClient:
    """
    Base class for web socket notification using broker (redis or rabbitmq)
    """

    connection = None

    def __init__(self, url):
        self.url = url
        self.connect()
        self.channel = self.connection.channel()
        self.socket_exchange = Exchange(exchange_name,
                                        type='fanout',
                                        channel=self.channel)
        self.socket_exchange.declare()

    def open(self):
        """Test if connection is open.

        True if connected else false

        :return bool:
        """
        return self.connection and self.connection.connected

    def connect(self):
        self._close()
        logger.info('Connecting to broker {}'.format(self.url))
        self.connection = Connection(self.url)
        self.connection.connect()
        logger.info('Connected to broker {}'.format(self.url))

    def _close(self):
        if hasattr(self, 'connection') and self.connection:
            logger.info('Closing connecting to broker {}'.format(self.url))
            self.connection.release()
            self.connection = None
            logger.info('Connection closed to broker {}'.format(self.url))

    def close(self):
        self._close()
Beispiel #38
0
def run(rabbit_url):
    print rabbit_url
    conn = Connection(rabbit_url)
    conn.ensure_connection()
    conn.connect()
    exchange = Exchange(config.EXCHANGE_NAME, type='direct')
    queue = Queue(name=config.QUEUE_NAME,
                  exchange=exchange,
                  routing_key=config.ROUTING_KEY)
    consumer = Consumer(conn,
                        queues=queue,
                        callbacks=[process_message],
                        accept=['text/plain'])
    consumer.consume()

    while True:
        try:
            print 'drain_events'
            conn.drain_events(timeout=2)  # timeout
        except socket.timeout:
            pass
class SocketBrokerClient:
    """
    Base class for web socket notification using broker (redis or rabbitmq)
    """

    connection = None

    def __init__(self, url, exchange_name=None):
        self.url = url
        self.connect()
        self.exchange_name = exchange_name if exchange_name else celery_queue('socket_notification')
        self.channel = self.connection.channel()
        self.socket_exchange = Exchange(self.exchange_name, type='fanout', channel=self.channel)
        self.socket_exchange.declare()

    def open(self):
        """Test if connection is open.

        True if connected else false

        :return bool:
        """
        return self.connection and self.connection.connected

    def connect(self):
        self._close()
        logger.info('Connecting to broker {}'.format(self.url))
        self.connection = Connection(self.url, heartbeat=WS_HEART_BEAT)
        self.connection.connect()
        logger.info('Connected to broker {}'.format(self.url))

    def _close(self):
        if hasattr(self, 'connection') and self.connection:
            logger.info('Closing connecting to broker {}'.format(self.url))
            self.connection.release()
            self.connection = None
            logger.info('Connection closed to broker {}'.format(self.url))

    def close(self):
        self._close()
Beispiel #40
0
def init(username, msgtype):
    global __username, __my_type, __connection, __global_exchange, __producer, __my_queue, __backchannel, __backch_producer, __adv_exchange, __adv_queue
    __username = username
    __my_type = msgtype
    print "Username: "******"Q:"
    #print __my_queue
    #__consumer = __connection.Consumer(queues=__my_queue) #we're not using consumer 'cause we're using queue get

    #__recv_loop =  drain_consumer(__consumer, timeout=1)

    __backchannel = Connection('amqp://')
    __backchannel.connect()
    __adv_exchange = Exchange('adversary', durable=False, delivery_mode=1)
    __adv_exchange.maybe_bind(__backchannel)
    __backch_producer = __backchannel.Producer(__backchannel)
    __adv_queue = Queue(username + '-adv',
                        exchange=__adv_exchange,
                        routing_key=username + '-adv',
                        durable=False)
    __adv_queue = __adv_queue(__backchannel)
    __adv_queue.declare()
Beispiel #41
0
class Publisher(object):
    def __init__(self, connection_string, exchange, is_active=True):
        self._is_active = is_active
        self.is_connected = True
        if not is_active:
            self.is_connected = False
            return

        self._connection = Connection(connection_string)
        self._connections = set([self._connection])  # set of connection for the heartbeat
        self._exchange = Exchange(exchange, durable=True, delivry_mode=2, type='topic')
        self._connection.connect()
        monitor_heartbeats(self._connections)

    def _get_producer(self):
        producer = producers[self._connection].acquire(block=True, timeout=2)
        self._connections.add(producer.connection)
        return producer

    def errback(self, exc, interval):
        logging.getLogger(__name__).info('Error: %r', exc, exc_info=1)
        logging.getLogger(__name__).info('Retry in %s seconds.', interval)

    def publish(self, item, contributor):
        if not self._is_active:
            logging.getLogger(__name__).info('RabbitMQ is not enabled')
            return True

        with self._get_producer() as producer:
            try:
                self.is_connected = True
                publish = producer.connection.ensure(producer, producer.publish, errback=self.errback, max_retries=3)
                publish(item, exchange=self._exchange, routing_key=contributor, declare=[self._exchange])
                logging.getLogger(__name__).info('Publishing message on exchange %s', self._exchange.name)
            except Exception, e:
                self.is_connected = False
                logging.getLogger(__name__).exception("Impossible to publish message to rabbitmq")
                logging.getLogger(__name__).exception(repr(e))
            finally:
class SocketBrokerClient:
    """
    Base class for web socket notification using broker (redis or rabbitmq)

    """

    connection = None

    def __init__(self, url):
        self.url = url
        self.connect()
        self.channel = self.connection.channel()
        self.socket_exchange = Exchange(exchange_name, type="fanout", channel=self.channel)
        self.socket_exchange.declare()

    def open(self):
        """
        True if connected else false
        :return bool:
        """
        return self.connection and self.connection.connected

    def connect(self):
        self._close()
        logger.info("Connecting to broker {}".format(self.url))
        self.connection = Connection(self.url)
        self.connection.connect()
        logger.info("Connected to broker {}".format(self.url))

    def _close(self):
        if hasattr(self, "connection") and self.connection:
            logger.info("Closing connecting to broker {}".format(self.url))
            self.connection.release()
            self.connection = None
            logger.info("Connection closed to broker {}".format(self.url))

    def close(self):
        self._close()
Beispiel #43
0
def check_server_access(sconf):
    servers = ["broker server", "results server"]

    if sconf.keys():
        print("\nChecking server connections:")
        print("-" * 28)

    excpts = {}
    for s in servers:
        if s in sconf:
            try:
                conn = Connection(sconf[s])
                conn.connect()
                conn.release()
                print(f"{s} connection: OK")
            except Exception as e:
                print(f"{s} connection: Error")
                excpts[s] = e

    if excpts:
        print("\nExceptions:")
        for k, v in excpts.items():
            print(f"{k}: {v}")
Beispiel #44
0
class rpc(object):
    def __init__(self):
        self.exchange = None
        self.connection = None
        self.connection_pool = None
        self.queue = {}
        self.consumer = {}
        self.producer = {}
        self.callbacks = {}

    def init_exchange(self, name = 'AllChat', type = 'direct', channel = None, durable = True, delivery_mode = 2):
        if self.exchange is None:
            self.exchange = Exchange(name, type, channel = channel, durable = durable, delivery_mode = delivery_mode)
        return self.exchange

    def init_connection(self,url,ssl = False):
        if self.connection is None:
            self.connection = Connection(url, ssl = ssl)
            try:
                self.connection.connect()
            except Exception as e:
                raise e
            else:
                self.connection.close()
        return self.connection

    def get_exchange(self):
        if self.exchange is None:
            raise Exception("No exchange. Please invoke init_exchange firstly")
        else:
            return self.exchange

    def create_connection(self):
        if self.connection_pool is None:
            self.connection_pool = self.connection.Pool(allchat.app.config['RPC_POOL_NUM'])
        return self.connection_pool.acquire()

    def release_connection(self, conn):
        try:
            if conn is not None:
                conn.release()
        except Exception as e:
            raise e

    def close_connection(self, conn):
        try:
            if conn is not None:
                conn.close()
        except Exception as e:
            raise e

    # def create_channel(self, conn):
    #     if conn is not None:
    #         return conn.channel()
    #     else:
    #         return None
    #
    # def release_channel(self, channel):
    #     try:
    #         if channel is not None:
    #             channel.close()
    #     except Exception as e:
    #         raise e

    # def create_consumer(self, name, channel , queues = None, callbacks = None):
    #     if name in self.consumer:
    #         self.consumer[name].revive(channel)
    #     else:
    #         if not any([queues, callbacks]):
    #             raise Exception("queues and callbacks can't be None")
    #         if isinstance(callbacks, list):
    #             self.consumer[name] = Consumer(channel, queues, callbacks)
    #         else:
    #             self.consumer[name] = Consumer(channel, queues)
    #             self.consumer[name].register_callback(callbacks)
    #     self.consumer[name].consume()
    #     return self.consumer[name]

    def create_consumer(self, name, channel, queues = None):
        if name in self.consumer:
            try:
                if self.callbacks[name] != self.consumer[name].callbacks:
                    self.consumer[name].callbacks = self.callbacks[name]
            except KeyError as e:
                raise Exception("Please invoke register_callbacks before")
            self.consumer[name].revive(channel)
        else:
            if not queues:
                queues = self.create_queue(name, name)
            try:
                self.callbacks[name]
            except KeyError as e:
                self.register_callbacks(name, [rpc_callbacks()])
                #raise Exception("Please invoke register_callbacks before")
            finally:
                self.consumer[name] = Consumer(channel, queues, callbacks = self.callbacks[name])
        #self.consumer[name].consume()
        return self.consumer[name]

    def release_consumer(self, name):
        try:
            if name in self.consumer:
                self.consumer[name].cancel()
        except Exception as e:
            raise e

    def create_producer(self, name, channel):
        if name in self.producer:
            self.producer[name].revive(channel)
        else:
            self.producer[name] = Producer(channel, self.get_exchange())
        return self.producer[name]

    def release_producer(self, name):
        try:
            if name in self.producer:
                self.producer[name].close()
        except Exception as e:
            raise e

    def create_queue(self, name, routing_key, durable = True):
        if name not in self.queue:
            self.queue[name] = Queue(name, self.get_exchange(), routing_key, durable = durable)
        return self.queue[name]

    def del_queue(self, name):
        try:
            if name in self.callbacks:
                del self.callbacks[name]
            if name in self.consumer:
                try:
                    self.consumer[name].close()
                except Exception as e:
                    pass
                del self.consumer[name]
            if name in self.producer:
                try:
                    self.producer[name].close()
                except Exception as e:
                    pass
                del self.producer[name]
            if name in self.queue:
                tmp = self.create_connection() #Kombu中删除Queue,必须保证Queue是绑定在一个channel上的,否则删除失败
                self.queue[name].maybe_bind(tmp)
                self.queue[name].delete()
                self.close_connection(tmp)
                del self.queue[name]
        except Exception as e:
            raise e

    def register_callbacks(self, name, callbacks):
        if isinstance(callbacks, list):
            self.callbacks[name] = callbacks
        else:
            raise Exception("The parameter callbacks should be a list")

    def extend_callbacks(self, name, callbacks):
        if isinstance(callbacks, list):
            if name in self.callbacks:
                self.callbacks[name].extend(callbacks)
            else:
                raise Exception("The {account} callbacks don't exist".format(account = name))
        else:
            raise Exception("The parameter callbacks should be a list")
Beispiel #45
0
class test_Consumer(TestCase):

    def setUp(self):
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        self.assertTrue(self.connection.connection.connected)
        self.exchange = Exchange('foo', 'direct')

    def test_set_no_ack(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True, no_ack=True)
        self.assertTrue(consumer.no_ack)

    def test_add_queue_when_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=True)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        self.assertIn(q, consumer.queues)
        q.declare.assert_called_with()

    def test_add_queue_when_not_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=False)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        self.assertIn(q, consumer.queues)
        self.assertFalse(q.declare.call_count)

    def test_consume_without_queues_returns(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = []
        self.assertIsNone(consumer.consume())

    def test_consuming_from(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = [Queue('a'), Queue('b')]
        self.assertFalse(consumer.consuming_from(Queue('c')))
        self.assertFalse(consumer.consuming_from('c'))
        self.assertTrue(consumer.consuming_from(Queue('a')))
        self.assertTrue(consumer.consuming_from(Queue('b')))
        self.assertTrue(consumer.consuming_from('b'))

    def test_receive_callback_without_m2p(self):
        channel = self.connection.channel()
        c = channel.Consumer()
        m2p = getattr(channel, 'message_to_python')
        channel.message_to_python = None
        try:
            message = Mock()
            message.decode.return_value = 'Hello'
            recv = c.receive = Mock()
            c._receive_callback(message)
            recv.assert_called_with('Hello', message)
        finally:
            channel.message_to_python = m2p

    def test_set_callbacks(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        callbacks = [lambda x, y: x,
                     lambda x, y: x]
        consumer = Consumer(channel, queue, auto_declare=True,
                            callbacks=callbacks)
        self.assertEqual(consumer.callbacks, callbacks)

    def test_auto_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.consume()  # twice is a noop
        self.assertIsNot(consumer.queues[0], queue)
        self.assertTrue(consumer.queues[0].is_bound)
        self.assertTrue(consumer.queues[0].exchange.is_bound)
        self.assertIsNot(consumer.queues[0].exchange, self.exchange)

        for meth in ('exchange_declare',
                     'queue_declare',
                     'queue_bind',
                     'basic_consume'):
            self.assertIn(meth, channel)
        self.assertEqual(channel.called.count('basic_consume'), 1)
        self.assertTrue(consumer._active_tags)

        consumer.cancel_by_queue(queue.name)
        consumer.cancel_by_queue(queue.name)
        self.assertFalse(consumer._active_tags)

    def test_manual_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=False)
        self.assertIsNot(consumer.queues[0], queue)
        self.assertTrue(consumer.queues[0].is_bound)
        self.assertTrue(consumer.queues[0].exchange.is_bound)
        self.assertIsNot(consumer.queues[0].exchange, self.exchange)

        for meth in ('exchange_declare',
                     'queue_declare',
                     'basic_consume'):
            self.assertNotIn(meth, channel)

        consumer.declare()
        for meth in ('exchange_declare',
                     'queue_declare',
                     'queue_bind'):
            self.assertIn(meth, channel)
        self.assertNotIn('basic_consume', channel)

        consumer.consume()
        self.assertIn('basic_consume', channel)

    def test_consume__cancel(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.cancel()
        self.assertIn('basic_cancel', channel)
        self.assertFalse(consumer._active_tags)

    def test___enter____exit__(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        context = consumer.__enter__()
        self.assertIs(context, consumer)
        self.assertTrue(consumer._active_tags)
        res = consumer.__exit__(None, None, None)
        self.assertFalse(res)
        self.assertIn('basic_cancel', channel)
        self.assertFalse(consumer._active_tags)

    def test_flow(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.flow(False)
        self.assertIn('flow', channel)

    def test_qos(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.qos(30, 10, False)
        self.assertIn('basic_qos', channel)

    def test_purge(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4], auto_declare=True)
        consumer.purge()
        self.assertEqual(channel.called.count('queue_purge'), 4)

    def test_multiple_queues(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4])
        consumer.consume()
        self.assertEqual(channel.called.count('exchange_declare'), 4)
        self.assertEqual(channel.called.count('queue_declare'), 4)
        self.assertEqual(channel.called.count('queue_bind'), 4)
        self.assertEqual(channel.called.count('basic_consume'), 4)
        self.assertEqual(len(consumer._active_tags), 4)
        consumer.cancel()
        self.assertEqual(channel.called.count('basic_cancel'), 4)
        self.assertFalse(len(consumer._active_tags))

    def test_receive_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        received = []

        def callback(message_data, message):
            received.append(message_data)
            message.ack()
            message.payload     # trigger cache

        consumer.register_callback(callback)
        consumer._receive_callback({u'foo': u'bar'})

        self.assertIn('basic_ack', channel)
        self.assertIn('message_to_python', channel)
        self.assertEqual(received[0], {u'foo': u'bar'})

    def test_basic_ack_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.ack()
            message.ack()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})

    def test_basic_reject(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject', channel)

    def test_basic_reject_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()
            message.reject()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject', channel)

    def test_basic_reject__requeue(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject:requeue', channel)

    def test_basic_reject__requeue_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()
            message.requeue()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject:requeue', channel)

    def test_receive_without_callbacks_raises(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        with self.assertRaises(NotImplementedError):
            consumer.receive(1, 2)

    def test_decode_error(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.channel.throw_decode_error = True

        with self.assertRaises(ValueError):
            consumer._receive_callback({'foo': 'bar'})

    def test_on_decode_error_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        thrown = []

        def on_decode_error(msg, exc):
            thrown.append((msg.body, exc))

        consumer = Consumer(channel, [b1], on_decode_error=on_decode_error)
        consumer.channel.throw_decode_error = True
        consumer._receive_callback({'foo': 'bar'})

        self.assertTrue(thrown)
        m, exc = thrown[0]
        self.assertEqual(anyjson.loads(m), {'foo': 'bar'})
        self.assertIsInstance(exc, ValueError)

    def test_recover(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.recover()
        self.assertIn('basic_recover', channel)

    def test_revive(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        channel2 = self.connection.channel()
        consumer.revive(channel2)
        self.assertIs(consumer.channel, channel2)
        self.assertIs(consumer.queues[0].channel, channel2)
        self.assertIs(consumer.queues[0].exchange.channel, channel2)

    def test__repr__(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        self.assertTrue(repr(Consumer(channel, [b1])))

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Consumer()
        p.channel = object()
        self.assertIsNone(p.connection)
Beispiel #46
0
class test_Producer(TestCase):

    def setUp(self):
        self.exchange = Exchange('foo', 'direct')
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        self.assertTrue(self.connection.connection.connected)
        self.assertFalse(self.exchange.is_bound)

    @patch('kombu.common.maybe_declare')
    def test_maybe_declare(self, maybe_declare):
        p = self.connection.Producer()
        q = Queue('foo')
        p.maybe_declare(q)
        maybe_declare.assert_called_with(q, p.channel, False)

    @patch('kombu.common.maybe_declare')
    def test_maybe_declare_when_entity_false(self, maybe_declare):
        p = self.connection.Producer()
        p.maybe_declare(None)
        self.assertFalse(maybe_declare.called)

    def test_auto_declare(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, auto_declare=True)
        self.assertIsNot(p.exchange, self.exchange,
                         'creates Exchange clone at bind')
        self.assertTrue(p.exchange.is_bound)
        self.assertIn('exchange_declare', channel,
                      'auto_declare declares exchange')

    def test_manual_declare(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, auto_declare=False)
        self.assertTrue(p.exchange.is_bound)
        self.assertNotIn('exchange_declare', channel,
                         'auto_declare=False does not declare exchange')
        p.declare()
        self.assertIn('exchange_declare', channel,
                      'p.declare() declares exchange')

    def test_prepare(self):
        message = {u'the quick brown fox': u'jumps over the lazy dog'}
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        m, ctype, cencoding = p._prepare(message, headers={})
        self.assertDictEqual(message, anyjson.loads(m))
        self.assertEqual(ctype, 'application/json')
        self.assertEqual(cencoding, 'utf-8')

    def test_prepare_compression(self):
        message = {u'the quick brown fox': u'jumps over the lazy dog'}
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        headers = {}
        m, ctype, cencoding = p._prepare(message, compression='zlib',
                                         headers=headers)
        self.assertEqual(ctype, 'application/json')
        self.assertEqual(cencoding, 'utf-8')
        self.assertEqual(headers['compression'], 'application/x-gzip')
        import zlib
        self.assertEqual(anyjson.loads(
                            zlib.decompress(m).decode('utf-8')), message)

    def test_prepare_custom_content_type(self):
        message = 'the quick brown fox'.encode('utf-8')
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        m, ctype, cencoding = p._prepare(message, content_type='custom')
        self.assertEqual(m, message)
        self.assertEqual(ctype, 'custom')
        self.assertEqual(cencoding, 'binary')
        m, ctype, cencoding = p._prepare(message, content_type='custom',
                                         content_encoding='alien')
        self.assertEqual(m, message)
        self.assertEqual(ctype, 'custom')
        self.assertEqual(cencoding, 'alien')

    def test_prepare_is_already_unicode(self):
        message = u'the quick brown fox'
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        m, ctype, cencoding = p._prepare(message, content_type='text/plain')
        self.assertEqual(m, message.encode('utf-8'))
        self.assertEqual(ctype, 'text/plain')
        self.assertEqual(cencoding, 'utf-8')
        m, ctype, cencoding = p._prepare(message, content_type='text/plain',
                                        content_encoding='utf-8')
        self.assertEqual(m, message.encode('utf-8'))
        self.assertEqual(ctype, 'text/plain')
        self.assertEqual(cencoding, 'utf-8')

    def test_publish_with_Exchange_instance(self):
        p = self.connection.Producer()
        p.channel = Mock()
        p.publish('hello', exchange=Exchange('foo'))
        self.assertEqual(
            p._channel.basic_publish.call_args[1]['exchange'], 'foo',
        )

    def test_publish_retry_with_declare(self):
        p = self.connection.Producer()
        p.maybe_declare = Mock()
        p.connection.ensure = Mock()
        ex = Exchange('foo')
        p._publish('hello', 0, '', '', {}, {}, 'rk', 0, 0, ex, declare=[ex])
        p.maybe_declare.assert_called_with(ex)

    def test_revive_when_channel_is_connection(self):
        p = self.connection.Producer()
        p.exchange = Mock()
        new_conn = Connection('memory://')
        defchan = new_conn.default_channel
        p.revive(new_conn)

        self.assertIs(p.channel, defchan)
        p.exchange.revive.assert_called_with(defchan)

    def test_enter_exit(self):
        p = self.connection.Producer()
        p.release = Mock()

        self.assertIs(p.__enter__(), p)
        p.__exit__()
        p.release.assert_called_with()

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Producer()
        p.channel = object()
        p.__connection__ = None
        self.assertIsNone(p.connection)

    def test_publish(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        message = {u'the quick brown fox': u'jumps over the lazy dog'}
        ret = p.publish(message, routing_key='process')
        self.assertIn('prepare_message', channel)
        self.assertIn('basic_publish', channel)

        m, exc, rkey = ret
        self.assertDictEqual(message, anyjson.loads(m['body']))
        self.assertDictContainsSubset({'content_type': 'application/json',
                                       'content_encoding': 'utf-8',
                                       'priority': 0}, m)
        self.assertDictContainsSubset({'delivery_mode': 2}, m['properties'])
        self.assertEqual(exc, p.exchange.name)
        self.assertEqual(rkey, 'process')

    def test_no_exchange(self):
        chan = self.connection.channel()
        p = Producer(chan)
        self.assertFalse(p.exchange.name)

    def test_revive(self):
        chan = self.connection.channel()
        p = Producer(chan)
        chan2 = self.connection.channel()
        p.revive(chan2)
        self.assertIs(p.channel, chan2)
        self.assertIs(p.exchange.channel, chan2)

    def test_on_return(self):
        chan = self.connection.channel()

        def on_return(exception, exchange, routing_key, message):
            pass

        p = Producer(chan, on_return=on_return)
        self.assertTrue(on_return in chan.events['basic_return'])
        self.assertTrue(p.on_return)
Beispiel #47
0
class Amqp(Thread):
    def __init__(
            self,
            host="localhost",
            port=5672,
            userid="guest",
            password="******",
            virtual_host="canopsis",
            exchange_name="canopsis",
            logging_name="Amqp",
            logging_level=INFO,
            read_config_file=True,
            auto_connect=True,
            on_ready=None,
            max_retries=5
    ):
        super(Amqp, self).__init__()

        self.logger = getLogger(logging_name)

        self.host = host
        self.port = port
        self.userid = userid
        self.password = password
        self.virtual_host = virtual_host
        self.exchange_name = exchange_name
        self.logging_level = logging_level

        if read_config_file:
            self.read_config("amqp")

        self.amqp_uri = "amqp://{0}:{1}@{2}:{3}/{4}".format(
            self.userid, self.password, self.host, self.port,
            self.virtual_host)

        self.logger.setLevel(logging_level)

        # Event sent try count before event drop in case of connection problem
        if max_retries != 5:
            self.logger.info('Custom retries value : {} {}'.format(
                max_retries,
                type(max_retries)
            ))
        self.max_retries = max_retries

        self.exchange_name_events = exchange_name + ".events"
        self.exchange_name_alerts = exchange_name + ".alerts"
        self.exchange_name_incidents = exchange_name + ".incidents"

        self.chan = None
        self.conn = None
        self.connected = False
        self.on_ready = on_ready

        self.RUN = True

        self.exchanges = {}

        self.queues = {}
        self.producers = None

        self.paused = False

        self.connection_errors = (
            ConnectionError,
            error,
            IOError,
            OSError)

        # Create exchange
        self.logger.debug("Create exchanges object")
        for exchange_name in [
                self.exchange_name, self.exchange_name_events,
                self.exchange_name_alerts, self.exchange_name_incidents]:
            self.logger.debug(' + {}'.format(exchange_name))
            self.get_exchange(exchange_name)

        if auto_connect:
            self.connect()

        self.logger.debug("Object canamqp initialized")

    def run(self):

        """
        main thread loop
        - connects to rabbit
        - calls drain_events
        - disconnects on error
        """
        self.logger.debug("Start thread ...")
        reconnect = False

        while self.RUN:

            self.connect()

            if self.connected:
                self.init_queue(reconnect=reconnect)

                self.logger.debug("Drain events ...")
                while self.RUN:
                    try:
                        if not self.paused:
                            self.conn.drain_events(timeout=0.5)
                        else:
                            sleep(0.5)

                    except KombuSerializationError as exc:
                        self.logger.error(
                            "Kombu serialization error: invalid message "
                            "received: {}".format(exc))

                    except timeout:
                        pass

                    except self.connection_errors as err:
                        self.logger.error(
                            "Connection error ! ({})".format(err)
                        )
                        break

                    except KombuSerializationError as exc:
                        self.logger.error(
                            "Kombu serialization error: invalid message "
                            "received: {}".format(exc))

                    except Exception as err:
                        self.logger.error("Error: {} ({})".format(
                            err,
                            type(err)
                        ))
                        print_exc(file=stdout)
                        break

                self.disconnect()

            if self.RUN:
                self.logger.error(
                    'Connection lost, try to reconnect in few seconds ...'
                )
                reconnect = True
                self.wait_connection(timeout=5)

        self.logger.debug("End of thread ...")

    def stop(self):
        self.logger.debug("Stop thread ...")
        self.RUN = False

    def connect(self):
        """
        Create the connection
        Inits the producers
        Init the only channel
        Declares exchanges
        """
        if not self.connected:
            self.logger.info(
                "Connect to AMQP Broker (%s:%s)" % (self.host, self.port))

            self.conn = Connection(self.amqp_uri)

            try:
                self.logger.debug(" + Connect")
                self.conn.connect()
                self.logger.info("Connected to AMQP Broker.")
                self.producers = pools.Producers(limit=10)
                self.connected = True
            except Exception as err:
                self.conn.release()
                self.logger.error("Impossible to connect ({})".format(err))

            if self.connected:
                self.logger.debug(" + Open channel")
                try:
                    self.chan = self.conn.channel()

                    self.logger.info("Channel openned. Ready to send messages")

                    try:
                        # Declare exchange
                        self.logger.debug("Declare exchanges")
                        for exchange_name in self.exchanges:
                            self.logger.debug(" + {}".format(exchange_name))
                            self.exchanges[exchange_name](self.chan).declare()
                    except Exception as err:
                        self.logger.error(
                            "Impossible to declare exchange ({})".format(err))

                except Exception as err:
                    self.logger.error(err)
        else:
            self.logger.debug("Already connected")

    def get_exchange(self, name):
        """
        Returns an exchange if stored in self.exchanges.
        Otherwise, creates it and returns it

        :param string name:  name of the exchange to get/create
        :rtype: Exchange|None
        """
        if name:
            try:
                return self.exchanges[name]
            except Exception:
                if name == "amq.direct":
                    self.exchanges[name] = Exchange(
                        name, "direct", durable=True)
                else:
                    self.exchanges[name] = Exchange(
                        name, "topic", durable=True, auto_delete=False)
                return self.exchanges[name]
        else:
            return None

    def init_queue(self, reconnect=False):
        """
        Loads queue settings
        Creates queues and attaches the same channel to each of them
        Binds queues to exchange
        Revives or creates consumers
        calls consume
        """
        if self.queues:
            self.logger.debug("Init queues")
            for queue_name in self.queues.keys():
                self.logger.debug(" + {}".format(queue_name))
                qsettings = self.queues[queue_name]

                if not qsettings['queue']:
                    self.logger.debug("   + Create queue")

                    # copy list
                    routing_keys = list(qsettings['routing_keys'])
                    routing_key = None

                    if len(routing_keys):
                        routing_key = routing_keys[0]
                        routing_keys = routing_keys[1:]

                    exchange = self.get_exchange(qsettings['exchange_name'])

                    if qsettings['exchange_name'] == "amq.direct" \
                            and not routing_key:
                        routing_key = queue_name

                    self.logger.debug(
                        "exchange: '{}', exclusive: {},"
                        " auto_delete: {},no_ack: {}"
                        .format(
                            qsettings['exchange_name'],
                            qsettings['exclusive'],
                            qsettings['auto_delete'],
                            qsettings['no_ack']
                        )
                    )
                    qsettings['queue'] = Queue(
                        queue_name,
                        exchange=exchange,
                        routing_key=routing_key,
                        exclusive=qsettings['exclusive'],
                        auto_delete=qsettings['auto_delete'],
                        no_ack=qsettings['no_ack'],
                        channel=self.conn.channel())

                    qsettings['queue'].declare()

                    if len(routing_keys):
                        self.logger.debug(" + Bind on all routing keys")
                        for routing_key in routing_keys:
                            self.logger.debug(
                                " + routing_key: '{}'".format(routing_key)
                            )
                            try:
                                qsettings['queue'].bind_to(
                                    exchange=exchange,
                                    routing_key=routing_key
                                )
                            except Exception:
                                self.logger.error(
                                    "You need upgrade your Kombu version ({})"
                                    .format(__version__)
                                )

                if qsettings['consumer'] and not reconnect:
                    qsettings['consumer'].revive(self.chan)
                elif not qsettings['consumer'] or reconnect:
                    self.logger.debug("   + Create Consumer")
                    qsettings['consumer'] = self.conn.Consumer(
                        qsettings['queue'], callbacks=[qsettings['callback']])

                self.logger.debug("   + Consume queue")
                qsettings['consumer'].consume()

            if self.on_ready:
                self.on_ready()
        else:
            self.logger.info('Queue already inited')

    def add_queue(
            self,
            queue_name,
            routing_keys,
            callback,
            exchange_name=None,
            no_ack=True,
            exclusive=False,
            auto_delete=True
    ):
        """
        Initializes the queue configuration
        maps the callback on the queue
        """

        c_routing_keys = []

        if not isinstance(routing_keys, list):
            if isinstance(routing_keys, basestring):
                c_routing_keys = [routing_keys]
        else:
            c_routing_keys = routing_keys
        # aka if rk is nor a list nor a basetring, leave it empty

        if not exchange_name:
            exchange_name = self.exchange_name

        self.queues[queue_name] = {
            'queue': False,
            'consumer': False,
            'queue_name': queue_name,
            'routing_keys': c_routing_keys,
            'callback': callback,
            'exchange_name': exchange_name,
            'no_ack': no_ack,
            'exclusive': exclusive,
            'auto_delete': auto_delete
        }

    def publish(
            self,
            msg,
            routing_key,
            exchange_name=None,
            serializer="json",
            compression=None,
            content_type=None,
            content_encoding=None
    ):
        """
        Tries to publish an event
        In case of failure, tries to reconnect and retry until (self.max_retries)
        :returns: operation success status
        :rtype: bool
        """
        self.logger.warning("Publishing from old.rabbitmq.Amqp is deprecated")
        operation_success = False
        retries = 0

        while not operation_success and retries < self.max_retries:
            retries += 1

            if self.connected:

                if not exchange_name:
                    exchange_name = self.exchange_name

                with self.producers[self.conn].acquire(block=True) as producer:
                    try:
                        _msg = msg.copy()

                        Amqp._clean_msg_for_serialization(_msg)

                        exchange = self.get_exchange(
                            exchange_name.encode('utf-8'))
                        producer.publish(
                            _msg,
                            serializer=serializer,
                            compression=compression,
                            routing_key=routing_key,
                            exchange=exchange
                        )

                        self.logger.debug('publish {} in exchange {}'.format(
                            routing_key,
                            exchange_name
                        ))

                        operation_success = True

                    except AmqpStructError:
                        self.logger.warning(
                            'Malformed message: routing key is too long. '
                            'Cancelling message')
                        return False

                    except Exception:
                        self.logger.error(
                            ' + Impossible to send {}'
                            .format(traceback.format_exc())
                        )
                        self.disconnect()
                        self.connect()
                        self.init_queue(reconnect=False)
            else:
                self.logger.error('Not connected ... try reconnecting')
                self.connect()

            if not operation_success:
                # Event and it's information are buffered until next send retry
                self.logger.info('Retry count {}'.format(
                    retries
                ))

        if not operation_success:
            # Event and it's information are buffered until next send retry
            self.logger.error('Too much retries for event {}, give up'.format(
                routing_key
            ))

        return operation_success

    @staticmethod
    def _clean_msg_for_serialization(msg):
        from bson import objectid
        for key in msg:
            if isinstance(msg[key], objectid.ObjectId):
                msg[key] = str(msg[key])

    def cancel_queues(self):
        if self.connected:
            for queue_name in self.queues.keys():
                if self.queues[queue_name]['consumer']:
                    self.logger.debug(
                        " + Cancel consumer on {}".format(queue_name)
                    )
                    try:
                        self.queues[queue_name]['consumer'].cancel()
                    except Exception:
                        pass

                    del(self.queues[queue_name]['consumer'])
                    self.queues[queue_name]['consumer'] = False
                    del(self.queues[queue_name]['queue'])
                    self.queues[queue_name]['queue'] = False

    def disconnect(self):
        if self.connected:
            self.logger.info("Disconnect from AMQP Broker")

            self.cancel_queues()

            # Force producers closing to permit a clean reconnect after
            # ... especially on timeout errors
            self.producers[self.conn].force_close_all()

            for exchange in self.exchanges:
                del exchange
            self.exchanges = {}

            try:
                pools.reset()
            except Exception as err:
                self.logger.error(
                    "Impossible to reset kombu pools: {} ({})".format(
                        err, type(err)))

            try:
                self.conn.release()
                del self.conn
            except Exception as err:
                self.logger.error(
                    "Impossible to release connection: {} ({})".format(
                        err, type(err)))

            self.connected = False

    def wait_connection(self, timeout=5):
        i = 0
        while self.RUN and not self.connected and i < (timeout * 2):
            sleep(0.5)
            i += 1

    def read_config(self, name):

        filename = join(root_path, 'etc', '{0}.conf'.format(name))

        import ConfigParser
        self.config = ConfigParser.RawConfigParser()

        try:
            self.config.read(filename)

            section = 'master'

            self.host = self.config.get(section, "host")
            self.port = self.config.getint(section, "port")
            self.userid = self.config.get(section, "userid")
            self.password = self.config.get(section, "password")
            self.virtual_host = self.config.get(section, "virtual_host")
            self.exchange_name = self.config.get(section, "exchange_name")

        except Exception as err:
            self.logger.error(
                "Can't to load configurations ({}), use default ...".format(
                    err
                ))

    def __del__(self):
        self.stop()
def do_produce(use_predef_msgs=False):
    conn = Connection(amqp_hosts, failover_strategy='round-robin' )
    conn.ensure_connection(errback=on_ens_conn_err_cb)
    conn.connect()

    # bind xchg and Qs to the rmq connection, declare primary exchange
    bound_priTopicXchg = priTopicXchg(conn)
    bound_priTopicXchg.declare()
    """
    #  and all explicit Qs in rmq
    for i in priTopicExplicitQs:
        _bound_q = i(conn)
        try:
            _bound_q.declare()
        except Exception as e:
            print("unable to declare, exception type [%s], [%s]" %
                    (type(e), repr(e)))
            _bound_q.delete()
            _bound_q.declare()
    """

    producer = conn.Producer(serializer='json')

    if use_predef_msgs:
        for msg in msgs:
            if msg['topic'] == PRI_TOPIC_NAME:
                xchg = priTopicXchg
                qs = priTopicExplicitQs
            else:
                print("unknown topic [%s]" % msg['topic'])
     
            print("sending messages[%s], xchg[%s], topic[%s], routing[%s]"
                    % (msg['msg'], xchg, msg['topic'], msg['routing']))

            producer.publish(
                    msg['msg']
                    , exchange=xchg
                    , declare=[xchg] + qs  #  let declaration of the exchange and the explicit Qs
                    #,compression='zlib'
                    , compression='bzip2'
                    , routing_key=msg['routing']
                    # apparently expiration per message dont really work in kombu 3.0.32
                    #exipration=10 # 60*15 # 15 minutes
                    #,properties=properties
                    #,x-message-ttl=1000
                    )
     
            print("all predefined messages sent")

    try:
        while True:
            var = input('')
            print(var.split('route'))
            tmp = [i.strip(' ') for i in var.split('route')]
            if len(tmp) != 2:
                print("invalid msg [%s], need to be of form: [aaa bbb route x.y.z]" %
                      var)
                continue
            try:
                bound_priTopicXchg.publish(
                        bound_priTopicXchg.Message(tmp[0]),
                        routing_key=tmp[1]
                        )
            except conn.connection_errors + conn.channel_errors:
                print("connection [%s] went down , reconnect to the next one" %
                    conn.info())
                conn.close()
                conn.ensure_connection(errback=on_ens_conn_err_cb)
                bound_priTopicXchg = priTopicXchg(conn)
                bound_priTopicXchg.publish(
                    bound_priTopicXchg.Message(tmp[0]),
                    routing_key=tmp[1]
                )

    except (EOFError, KeyboardInterrupt):
        print("done")
Beispiel #49
0
from kombu import Connection
from tapiriik.settings import RABBITMQ_BROKER_URL
mq = Connection(RABBITMQ_BROKER_URL)
mq.connect()
Beispiel #50
0
def kombu_connection_test():
    connection = Connection('amqp://*****:*****@121.41.4.137:5672//')
    connection.connect()
    print connection.connected
    connection.release()
Beispiel #51
0
class _AMQPServerWrapper(object):
    def __init__(self, amqp_url):
        self.__connection = Connection(amqp_url)
        self.__connection.connect()
        self.__monitors = {}
        self.__running = True
        self.__consumer = Consumer(self.__connection, on_message=self.__on_message)
        self.__consumer_gl = gevent.spawn(self.__consumer_greenlet_main)

    def __consumer_greenlet_main(self):
        gevent.sleep(0)
        while self.__running:
            self.__consumer.consume()
            try:
                self.__connection.drain_events(timeout=0.1)
            except Exception as ex:     # NOQA: assigned but not used (left in for super-duper-low-level-debug)
                # print("was woken because {}".format(ex))
                pass
            gevent.sleep(0)
            # print("---loop")

    def __on_message(self, msg):
        ct = msg.delivery_info['consumer_tag']
        assert ct in self.__monitors, \
            "Message from consumer '{}', but we are not monitoring that (list={})".format(
                msg.delivery_info['consumer_tag'], self.__monitors.keys())
        mon = self.__monitors[ct]
        mon['event_cb'](msg, msg.body)

    @property
    def connected(self):
        return self.__connection.connected

    def create_add_monitor(self, exchange, routing_key, event_cb, queue_name=None):
        mname = "ex={} rk={} qn={}".format(exchange, routing_key, queue_name)
        if mname in self.__monitors:
            mon = self.__monitors[mname]
            mon["event_cb"] = event_cb
        else:
            if queue_name is None:
                queue_name = ''
                exclusive = True
            else:
                exclusive = False
            ex = Exchange(exchange, 'topic')
            queue = Queue(exchange=ex, routing_key=routing_key, exclusive=exclusive)
            bound_queue = queue.bind(self.__connection)
            self.__consumer.add_queue(bound_queue)
            bound_queue.consume(mname, self.__on_message)
            mon = {
                "event_cb": event_cb,
                "exchange": ex
            }
            self.__monitors[mname] = mon
        return mon['exchange']

    def inject(self, exchange, routing_key, payload):
        prod = Producer(self.__connection, exchange=exchange, routing_key=routing_key)
        prod.publish(payload)

    def test_helper_sync_send_msg(self, exchange, ex_rk, send_rk, payload):
        ex = Exchange(exchange, 'topic')
        queue = Queue(exchange=ex, routing_key=ex_rk + '.*', exclusive=True, channel=self.__connection)
        queue.declare()
        prod = Producer(self.__connection, exchange=ex, routing_key=send_rk)
        prod.publish(payload)
        return queue

    def test_helper_sync_recv_msg(self, queue):
        for tick in range(10):
            msg = queue.get()
            if msg is not None:
                break
            time.sleep(1)
        return msg
def do_consume(user_qs):

    print("about to listen no queues [%s]" %
          ", ".join(list(map(lambda x: x, user_qs))))

    conn = Connection(amqp_hosts, failover_strategy='round-robin')

    # try to get a connection no matter what
    while True:
        try:
            conn.ensure_connection(errback=on_ens_conn_err_cb)
            conn.connect()
        except Exception as e:
            print("connection error failed on exception [%s]" % repr(e))
            conn.release()
            continue
        if conn.connected:
            break
        else:
            print("connection failed in some way, retry")

    chan = conn.channel()

    global bound_cons_Q

    cons_Q = Queue(common.uuid(), queue_arguments=q_expires)
    bound_cons_Q = cons_Q(chan)
    bound_cons_Q.declare()
    # first bind to some control route
    bound_cons_Q.bind_to(priTopicXchg, routing_key='manage.#')
    for i in user_qs:
        if '*' in i or '#' in i:
            # create the wildcard route_key bind
            bound_cons_Q.bind_to(priTopicXchg, routing_key=i)
        else:
            for j in allQs:
                if i == j.as_dict()['name']:
                    bound_cons_Q.bind_to(priTopicXchg, routing_key=j.as_dict()['routing_key'])

    cons = Consumer(
            chan,
            accept=['json'],
            queues=bound_cons_Q,
            callbacks=[on_msg_cb_1, on_msg_cb_2]
            )

    print("queue set to [%s]" % bound_cons_Q.as_dict(recurse=True))
    cons.consume()
    while True:
        try:
            
            conn.drain_events()
        except conn.connection_errors + conn.channel_errors as e:
            print("connection [%s] went down (error[%s]), trying to "
                  "connect to the next one" % (conn.info(), repr(e)))
            conn.close()
            conn.release()
            conn.ensure_connection(errback=on_ens_conn_err_cb)
            conn.connect()

            chan = conn.channel()
            cons_Q.bind(chan)
            cons = Consumer(
                    chan,
                    accept=['json'],
                    queues=bound_cons_Q,
                    callbacks=[on_msg_cb_1, on_msg_cb_2]
                    )
            cons.consume()
Beispiel #53
0
class test_Consumer:

    def setup(self):
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        assert self.connection.connection.connected
        self.exchange = Exchange('foo', 'direct')

    def test_accept(self):
        a = Consumer(self.connection)
        assert a.accept is None
        b = Consumer(self.connection, accept=['json', 'pickle'])
        assert b.accept == {
            'application/json', 'application/x-python-serialize',
        }
        c = Consumer(self.connection, accept=b.accept)
        assert b.accept == c.accept

    def test_enter_exit_cancel_raises(self):
        c = Consumer(self.connection)
        c.cancel = Mock(name='Consumer.cancel')
        c.cancel.side_effect = KeyError('foo')
        with c:
            pass
        c.cancel.assert_called_with()

    def test_receive_callback_accept(self):
        message = Mock(name='Message')
        message.errors = []
        callback = Mock(name='on_message')
        c = Consumer(self.connection, accept=['json'], on_message=callback)
        c.on_decode_error = None
        c.channel = Mock(name='channel')
        c.channel.message_to_python = None

        c._receive_callback(message)
        callback.assert_called_with(message)
        assert message.accept == c.accept

    def test_accept__content_disallowed(self):
        conn = Connection('memory://')
        q = Queue('foo', exchange=self.exchange)
        p = conn.Producer()
        p.publish(
            {'complex': object()},
            declare=[q], exchange=self.exchange, serializer='pickle',
        )

        callback = Mock(name='callback')
        with conn.Consumer(queues=[q], callbacks=[callback]) as consumer:
            with pytest.raises(consumer.ContentDisallowed):
                conn.drain_events(timeout=1)
        callback.assert_not_called()

    def test_accept__content_allowed(self):
        conn = Connection('memory://')
        q = Queue('foo', exchange=self.exchange)
        p = conn.Producer()
        p.publish(
            {'complex': object()},
            declare=[q], exchange=self.exchange, serializer='pickle',
        )

        callback = Mock(name='callback')
        with conn.Consumer(queues=[q], accept=['pickle'],
                           callbacks=[callback]):
            conn.drain_events(timeout=1)
        callback.assert_called()
        body, message = callback.call_args[0]
        assert body['complex']

    def test_set_no_channel(self):
        c = Consumer(None)
        assert c.channel is None
        c.revive(Mock())
        assert c.channel

    def test_set_no_ack(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True, no_ack=True)
        assert consumer.no_ack

    def test_add_queue_when_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=True)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        assert q in consumer.queues
        q.declare.assert_called_with()

    def test_add_queue_when_not_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=False)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        assert q in consumer.queues
        assert not q.declare.call_count

    def test_consume_without_queues_returns(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = []
        assert consumer.consume() is None

    def test_consuming_from(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = [Queue('a'), Queue('b'), Queue('d')]
        consumer._active_tags = {'a': 1, 'b': 2}

        assert not consumer.consuming_from(Queue('c'))
        assert not consumer.consuming_from('c')
        assert not consumer.consuming_from(Queue('d'))
        assert not consumer.consuming_from('d')
        assert consumer.consuming_from(Queue('a'))
        assert consumer.consuming_from(Queue('b'))
        assert consumer.consuming_from('b')

    def test_receive_callback_without_m2p(self):
        channel = self.connection.channel()
        c = channel.Consumer()
        m2p = getattr(channel, 'message_to_python')
        channel.message_to_python = None
        try:
            message = Mock()
            message.errors = []
            message.decode.return_value = 'Hello'
            recv = c.receive = Mock()
            c._receive_callback(message)
            recv.assert_called_with('Hello', message)
        finally:
            channel.message_to_python = m2p

    def test_receive_callback__message_errors(self):
        channel = self.connection.channel()
        channel.message_to_python = None
        c = channel.Consumer()
        message = Mock()
        try:
            raise KeyError('foo')
        except KeyError:
            message.errors = [sys.exc_info()]
        message._reraise_error.side_effect = KeyError()
        with pytest.raises(KeyError):
            c._receive_callback(message)

    def test_set_callbacks(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        callbacks = [lambda x, y: x,
                     lambda x, y: x]
        consumer = Consumer(channel, queue, auto_declare=True,
                            callbacks=callbacks)
        assert consumer.callbacks == callbacks

    def test_auto_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.consume()  # twice is a noop
        assert consumer.queues[0] is not queue
        assert consumer.queues[0].is_bound
        assert consumer.queues[0].exchange.is_bound
        assert consumer.queues[0].exchange is not self.exchange

        for meth in ('exchange_declare',
                     'queue_declare',
                     'queue_bind',
                     'basic_consume'):
            assert meth in channel
        assert channel.called.count('basic_consume') == 1
        assert consumer._active_tags

        consumer.cancel_by_queue(queue.name)
        consumer.cancel_by_queue(queue.name)
        assert not consumer._active_tags

    def test_consumer_tag_prefix(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, tag_prefix='consumer_')
        consumer.consume()

        assert consumer._active_tags[queue.name].startswith('consumer_')

    def test_manual_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=False)
        assert consumer.queues[0] is not queue
        assert consumer.queues[0].is_bound
        assert consumer.queues[0].exchange.is_bound
        assert consumer.queues[0].exchange is not self.exchange

        for meth in ('exchange_declare',
                     'queue_declare',
                     'basic_consume'):
            assert meth not in channel

        consumer.declare()
        for meth in ('exchange_declare',
                     'queue_declare',
                     'queue_bind'):
            assert meth in channel
        assert 'basic_consume' not in channel

        consumer.consume()
        assert 'basic_consume' in channel

    def test_consume__cancel(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.cancel()
        assert 'basic_cancel' in channel
        assert not consumer._active_tags

    def test___enter____exit__(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        context = consumer.__enter__()
        assert context is consumer
        assert consumer._active_tags
        res = consumer.__exit__(None, None, None)
        assert not res
        assert 'basic_cancel' in channel
        assert not consumer._active_tags

    def test_flow(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.flow(False)
        assert 'flow' in channel

    def test_qos(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.qos(30, 10, False)
        assert 'basic_qos' in channel

    def test_purge(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4], auto_declare=True)
        consumer.purge()
        assert channel.called.count('queue_purge') == 4

    def test_multiple_queues(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4])
        consumer.consume()
        assert channel.called.count('exchange_declare') == 4
        assert channel.called.count('queue_declare') == 4
        assert channel.called.count('queue_bind') == 4
        assert channel.called.count('basic_consume') == 4
        assert len(consumer._active_tags) == 4
        consumer.cancel()
        assert channel.called.count('basic_cancel') == 4
        assert not len(consumer._active_tags)

    def test_receive_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        received = []

        def callback(message_data, message):
            received.append(message_data)
            message.ack()
            message.payload     # trigger cache

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})

        assert 'basic_ack' in channel
        assert 'message_to_python' in channel
        assert received[0] == {'foo': 'bar'}

    def test_basic_ack_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.ack()
            message.ack()

        consumer.register_callback(callback)
        with pytest.raises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})

    def test_basic_reject(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        assert 'basic_reject' in channel

    def test_basic_reject_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()
            message.reject()

        consumer.register_callback(callback)
        with pytest.raises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        assert 'basic_reject' in channel

    def test_basic_reject__requeue(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        assert 'basic_reject:requeue' in channel

    def test_basic_reject__requeue_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()
            message.requeue()

        consumer.register_callback(callback)
        with pytest.raises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        assert 'basic_reject:requeue' in channel

    def test_receive_without_callbacks_raises(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        with pytest.raises(NotImplementedError):
            consumer.receive(1, 2)

    def test_decode_error(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.channel.throw_decode_error = True

        with pytest.raises(ValueError):
            consumer._receive_callback({'foo': 'bar'})

    def test_on_decode_error_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        thrown = []

        def on_decode_error(msg, exc):
            thrown.append((msg.body, exc))

        consumer = Consumer(channel, [b1], on_decode_error=on_decode_error)
        consumer.channel.throw_decode_error = True
        consumer._receive_callback({'foo': 'bar'})

        assert thrown
        m, exc = thrown[0]
        assert json.loads(m) == {'foo': 'bar'}
        assert isinstance(exc, ValueError)

    def test_recover(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.recover()
        assert 'basic_recover' in channel

    def test_revive(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        channel2 = self.connection.channel()
        consumer.revive(channel2)
        assert consumer.channel is channel2
        assert consumer.queues[0].channel is channel2
        assert consumer.queues[0].exchange.channel is channel2

    def test_revive__with_prefetch_count(self):
        channel = Mock(name='channel')
        b1 = Queue('qname1', self.exchange, 'rkey')
        Consumer(channel, [b1], prefetch_count=14)
        channel.basic_qos.assert_called_with(0, 14, False)

    def test__repr__(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        assert repr(Consumer(channel, [b1]))

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Consumer()
        p.channel = object()
        assert p.connection is None
Beispiel #54
0
class test_Producer:

    def setup(self):
        self.exchange = Exchange('foo', 'direct')
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        assert self.connection.connection.connected
        assert not self.exchange.is_bound

    def test_repr(self):
        p = Producer(self.connection)
        assert repr(p)

    def test_pickle(self):
        chan = Mock()
        producer = Producer(chan, serializer='pickle')
        p2 = pickle.loads(pickle.dumps(producer))
        assert p2.serializer == producer.serializer

    def test_no_channel(self):
        p = Producer(None)
        assert not p._channel

    @patch('kombu.messaging.maybe_declare')
    def test_maybe_declare(self, maybe_declare):
        p = self.connection.Producer()
        q = Queue('foo')
        p.maybe_declare(q)
        maybe_declare.assert_called_with(q, p.channel, False)

    @patch('kombu.common.maybe_declare')
    def test_maybe_declare_when_entity_false(self, maybe_declare):
        p = self.connection.Producer()
        p.maybe_declare(None)
        maybe_declare.assert_not_called()

    def test_auto_declare(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, auto_declare=True)
        # creates Exchange clone at bind
        assert p.exchange is not self.exchange
        assert p.exchange.is_bound
        # auto_declare declares exchange'
        assert 'exchange_declare' in channel

    def test_manual_declare(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, auto_declare=False)
        assert p.exchange.is_bound
        # auto_declare=False does not declare exchange
        assert 'exchange_declare' not in channel
        # p.declare() declares exchange')
        p.declare()
        assert 'exchange_declare' in channel

    def test_prepare(self):
        message = {'the quick brown fox': 'jumps over the lazy dog'}
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        m, ctype, cencoding = p._prepare(message, headers={})
        assert json.loads(m) == message
        assert ctype == 'application/json'
        assert cencoding == 'utf-8'

    def test_prepare_compression(self):
        message = {'the quick brown fox': 'jumps over the lazy dog'}
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        headers = {}
        m, ctype, cencoding = p._prepare(message, compression='zlib',
                                         headers=headers)
        assert ctype == 'application/json'
        assert cencoding == 'utf-8'
        assert headers['compression'] == 'application/x-gzip'
        import zlib
        assert json.loads(zlib.decompress(m).decode('utf-8')) == message

    def test_prepare_custom_content_type(self):
        message = 'the quick brown fox'.encode('utf-8')
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        m, ctype, cencoding = p._prepare(message, content_type='custom')
        assert m == message
        assert ctype == 'custom'
        assert cencoding == 'binary'
        m, ctype, cencoding = p._prepare(message, content_type='custom',
                                         content_encoding='alien')
        assert m == message
        assert ctype == 'custom'
        assert cencoding == 'alien'

    def test_prepare_is_already_unicode(self):
        message = 'the quick brown fox'
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        m, ctype, cencoding = p._prepare(message, content_type='text/plain')
        assert m == message.encode('utf-8')
        assert ctype == 'text/plain'
        assert cencoding == 'utf-8'
        m, ctype, cencoding = p._prepare(message, content_type='text/plain',
                                         content_encoding='utf-8')
        assert m == message.encode('utf-8')
        assert ctype == 'text/plain'
        assert cencoding == 'utf-8'

    def test_publish_with_Exchange_instance(self):
        p = self.connection.Producer()
        p.channel = Mock()
        p.publish('hello', exchange=Exchange('foo'), delivery_mode='transient')
        assert p._channel.basic_publish.call_args[1]['exchange'] == 'foo'

    def test_publish_with_expiration(self):
        p = self.connection.Producer()
        p.channel = Mock()
        p.publish('hello', exchange=Exchange('foo'), expiration=10)
        properties = p._channel.prepare_message.call_args[0][5]
        assert properties['expiration'] == '10000'

    def test_publish_with_reply_to(self):
        p = self.connection.Producer()
        p.channel = Mock()
        p.publish('hello', exchange=Exchange('foo'), reply_to=Queue('foo'))
        properties = p._channel.prepare_message.call_args[0][5]
        assert properties['reply_to'] == 'foo'

    def test_set_on_return(self):
        chan = Mock()
        chan.events = defaultdict(Mock)
        p = Producer(ChannelPromise(lambda: chan), on_return='on_return')
        p.channel
        chan.events['basic_return'].add.assert_called_with('on_return')

    def test_publish_retry_calls_ensure(self):
        p = Producer(Mock())
        p._connection = Mock()
        ensure = p.connection.ensure = Mock()
        p.publish('foo', exchange='foo', retry=True)
        ensure.assert_called()

    def test_publish_retry_with_declare(self):
        p = self.connection.Producer()
        p.maybe_declare = Mock()
        p.connection.ensure = Mock()
        ex = Exchange('foo')
        p._publish('hello', 0, '', '', {}, {}, 'rk', 0, 0, ex, declare=[ex])
        p.maybe_declare.assert_called_with(ex)

    def test_revive_when_channel_is_connection(self):
        p = self.connection.Producer()
        p.exchange = Mock()
        new_conn = Connection('memory://')
        defchan = new_conn.default_channel
        p.revive(new_conn)

        assert p.channel is defchan
        p.exchange.revive.assert_called_with(defchan)

    def test_enter_exit(self):
        p = self.connection.Producer()
        p.release = Mock()

        assert p.__enter__() is p
        p.__exit__()
        p.release.assert_called_with()

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Producer()
        p.channel = object()
        p.__connection__ = None
        assert p.connection is None

    def test_publish(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer='json')
        message = {'the quick brown fox': 'jumps over the lazy dog'}
        ret = p.publish(message, routing_key='process')
        assert 'prepare_message' in channel
        assert 'basic_publish' in channel

        m, exc, rkey = ret
        assert json.loads(m['body']) == message
        assert m['content_type'] == 'application/json'
        assert m['content_encoding'] == 'utf-8'
        assert m['priority'] == 0
        assert m['properties']['delivery_mode'] == 2
        assert exc == p.exchange.name
        assert rkey == 'process'

    def test_no_exchange(self):
        chan = self.connection.channel()
        p = Producer(chan)
        assert not p.exchange.name

    def test_revive(self):
        chan = self.connection.channel()
        p = Producer(chan)
        chan2 = self.connection.channel()
        p.revive(chan2)
        assert p.channel is chan2
        assert p.exchange.channel is chan2

    def test_on_return(self):
        chan = self.connection.channel()

        def on_return(exception, exchange, routing_key, message):
            pass

        p = Producer(chan, on_return=on_return)
        assert on_return in chan.events['basic_return']
        assert p.on_return
Beispiel #55
0
class test_Producer(TestCase):
    def setUp(self):
        self.exchange = Exchange("foo", "direct")
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        self.assertTrue(self.connection.connection.connected)
        self.assertFalse(self.exchange.is_bound)

    def test_pickle(self):
        chan = Mock()
        producer = Producer(chan, serializer="pickle")
        p2 = pickle.loads(pickle.dumps(producer))
        self.assertEqual(p2.serializer, producer.serializer)

    def test_no_channel(self):
        p = Producer(None)
        self.assertFalse(p._channel)

    @patch("kombu.common.maybe_declare")
    def test_maybe_declare(self, maybe_declare):
        p = self.connection.Producer()
        q = Queue("foo")
        p.maybe_declare(q)
        maybe_declare.assert_called_with(q, p.channel, False)

    @patch("kombu.common.maybe_declare")
    def test_maybe_declare_when_entity_false(self, maybe_declare):
        p = self.connection.Producer()
        p.maybe_declare(None)
        self.assertFalse(maybe_declare.called)

    def test_auto_declare(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, auto_declare=True)
        self.assertIsNot(p.exchange, self.exchange, "creates Exchange clone at bind")
        self.assertTrue(p.exchange.is_bound)
        self.assertIn("exchange_declare", channel, "auto_declare declares exchange")

    def test_manual_declare(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, auto_declare=False)
        self.assertTrue(p.exchange.is_bound)
        self.assertNotIn("exchange_declare", channel, "auto_declare=False does not declare exchange")
        p.declare()
        self.assertIn("exchange_declare", channel, "p.declare() declares exchange")

    def test_prepare(self):
        message = {"the quick brown fox": "jumps over the lazy dog"}
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer="json")
        m, ctype, cencoding = p._prepare(message, headers={})
        self.assertDictEqual(message, anyjson.loads(m))
        self.assertEqual(ctype, "application/json")
        self.assertEqual(cencoding, "utf-8")

    def test_prepare_compression(self):
        message = {"the quick brown fox": "jumps over the lazy dog"}
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer="json")
        headers = {}
        m, ctype, cencoding = p._prepare(message, compression="zlib", headers=headers)
        self.assertEqual(ctype, "application/json")
        self.assertEqual(cencoding, "utf-8")
        self.assertEqual(headers["compression"], "application/x-gzip")
        import zlib

        self.assertEqual(anyjson.loads(zlib.decompress(m).decode("utf-8")), message)

    def test_prepare_custom_content_type(self):
        message = "the quick brown fox".encode("utf-8")
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer="json")
        m, ctype, cencoding = p._prepare(message, content_type="custom")
        self.assertEqual(m, message)
        self.assertEqual(ctype, "custom")
        self.assertEqual(cencoding, "binary")
        m, ctype, cencoding = p._prepare(message, content_type="custom", content_encoding="alien")
        self.assertEqual(m, message)
        self.assertEqual(ctype, "custom")
        self.assertEqual(cencoding, "alien")

    def test_prepare_is_already_unicode(self):
        message = "the quick brown fox"
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer="json")
        m, ctype, cencoding = p._prepare(message, content_type="text/plain")
        self.assertEqual(m, message.encode("utf-8"))
        self.assertEqual(ctype, "text/plain")
        self.assertEqual(cencoding, "utf-8")
        m, ctype, cencoding = p._prepare(message, content_type="text/plain", content_encoding="utf-8")
        self.assertEqual(m, message.encode("utf-8"))
        self.assertEqual(ctype, "text/plain")
        self.assertEqual(cencoding, "utf-8")

    def test_publish_with_Exchange_instance(self):
        p = self.connection.Producer()
        p.channel = Mock()
        p.publish("hello", exchange=Exchange("foo"), delivery_mode="transient")
        self.assertEqual(p._channel.basic_publish.call_args[1]["exchange"], "foo")

    def test_set_on_return(self):
        chan = Mock()
        chan.events = defaultdict(Mock)
        p = Producer(ChannelPromise(lambda: chan), on_return="on_return")
        p.channel
        chan.events["basic_return"].add.assert_called_with("on_return")

    def test_publish_retry_calls_ensure(self):
        p = Producer(Mock())
        p._connection = Mock()
        ensure = p.connection.ensure = Mock()
        p.publish("foo", exchange="foo", retry=True)
        self.assertTrue(ensure.called)

    def test_publish_retry_with_declare(self):
        p = self.connection.Producer()
        p.maybe_declare = Mock()
        p.connection.ensure = Mock()
        ex = Exchange("foo")
        p._publish("hello", 0, "", "", {}, {}, "rk", 0, 0, ex, declare=[ex])
        p.maybe_declare.assert_called_with(ex)

    def test_revive_when_channel_is_connection(self):
        p = self.connection.Producer()
        p.exchange = Mock()
        new_conn = Connection("memory://")
        defchan = new_conn.default_channel
        p.revive(new_conn)

        self.assertIs(p.channel, defchan)
        p.exchange.revive.assert_called_with(defchan)

    def test_enter_exit(self):
        p = self.connection.Producer()
        p.release = Mock()

        self.assertIs(p.__enter__(), p)
        p.__exit__()
        p.release.assert_called_with()

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Producer()
        p.channel = object()
        p.__connection__ = None
        self.assertIsNone(p.connection)

    def test_publish(self):
        channel = self.connection.channel()
        p = Producer(channel, self.exchange, serializer="json")
        message = {"the quick brown fox": "jumps over the lazy dog"}
        ret = p.publish(message, routing_key="process")
        self.assertIn("prepare_message", channel)
        self.assertIn("basic_publish", channel)

        m, exc, rkey = ret
        self.assertDictEqual(message, anyjson.loads(m["body"]))
        self.assertDictContainsSubset(
            {"content_type": "application/json", "content_encoding": "utf-8", "priority": 0}, m
        )
        self.assertDictContainsSubset({"delivery_mode": 2}, m["properties"])
        self.assertEqual(exc, p.exchange.name)
        self.assertEqual(rkey, "process")

    def test_no_exchange(self):
        chan = self.connection.channel()
        p = Producer(chan)
        self.assertFalse(p.exchange.name)

    def test_revive(self):
        chan = self.connection.channel()
        p = Producer(chan)
        chan2 = self.connection.channel()
        p.revive(chan2)
        self.assertIs(p.channel, chan2)
        self.assertIs(p.exchange.channel, chan2)

    def test_on_return(self):
        chan = self.connection.channel()

        def on_return(exception, exchange, routing_key, message):
            pass

        p = Producer(chan, on_return=on_return)
        self.assertTrue(on_return in chan.events["basic_return"])
        self.assertTrue(p.on_return)
Beispiel #56
0
class test_Consumer(Case):
    def setUp(self):
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        self.assertTrue(self.connection.connection.connected)
        self.exchange = Exchange('foo', 'direct')

    def test_accept(self):
        a = Consumer(self.connection)
        self.assertIsNone(a.accept)
        b = Consumer(self.connection, accept=['json', 'pickle'])
        self.assertSetEqual(
            b.accept,
            set(['application/json', 'application/x-python-serialize']),
        )
        c = Consumer(self.connection, accept=b.accept)
        self.assertSetEqual(b.accept, c.accept)

    def test_enter_exit_cancel_raises(self):
        c = Consumer(self.connection)
        c.cancel = Mock(name='Consumer.cancel')
        c.cancel.side_effect = KeyError('foo')
        with c:
            pass
        c.cancel.assert_called_with()

    def test_receive_callback_accept(self):
        message = Mock(name='Message')
        message.errors = []
        callback = Mock(name='on_message')
        c = Consumer(self.connection, accept=['json'], on_message=callback)
        c.on_decode_error = None
        c.channel = Mock(name='channel')
        c.channel.message_to_python = None

        c._receive_callback(message)
        callback.assert_called_with(message)
        self.assertSetEqual(message.accept, c.accept)

    def test_accept__content_disallowed(self):
        conn = Connection('memory://')
        q = Queue('foo', exchange=self.exchange)
        p = conn.Producer()
        p.publish(
            {'complex': object()},
            declare=[q],
            exchange=self.exchange,
            serializer='pickle',
        )

        callback = Mock(name='callback')
        with conn.Consumer(queues=[q], callbacks=[callback]) as consumer:
            with self.assertRaises(consumer.ContentDisallowed):
                conn.drain_events(timeout=1)
        self.assertFalse(callback.called)

    def test_accept__content_allowed(self):
        conn = Connection('memory://')
        q = Queue('foo', exchange=self.exchange)
        p = conn.Producer()
        p.publish(
            {'complex': object()},
            declare=[q],
            exchange=self.exchange,
            serializer='pickle',
        )

        callback = Mock(name='callback')
        with conn.Consumer(queues=[q], accept=['pickle'],
                           callbacks=[callback]):
            conn.drain_events(timeout=1)
        self.assertTrue(callback.called)
        body, message = callback.call_args[0]
        self.assertTrue(body['complex'])

    def test_set_no_channel(self):
        c = Consumer(None)
        self.assertIsNone(c.channel)
        c.revive(Mock())
        self.assertTrue(c.channel)

    def test_set_no_ack(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True, no_ack=True)
        self.assertTrue(consumer.no_ack)

    def test_add_queue_when_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=True)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        self.assertIn(q, consumer.queues)
        q.declare.assert_called_with()

    def test_add_queue_when_not_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=False)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        self.assertIn(q, consumer.queues)
        self.assertFalse(q.declare.call_count)

    def test_consume_without_queues_returns(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = []
        self.assertIsNone(consumer.consume())

    def test_consuming_from(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = [Queue('a'), Queue('b'), Queue('d')]
        consumer._active_tags = {'a': 1, 'b': 2}

        self.assertFalse(consumer.consuming_from(Queue('c')))
        self.assertFalse(consumer.consuming_from('c'))
        self.assertFalse(consumer.consuming_from(Queue('d')))
        self.assertFalse(consumer.consuming_from('d'))
        self.assertTrue(consumer.consuming_from(Queue('a')))
        self.assertTrue(consumer.consuming_from(Queue('b')))
        self.assertTrue(consumer.consuming_from('b'))

    def test_receive_callback_without_m2p(self):
        channel = self.connection.channel()
        c = channel.Consumer()
        m2p = getattr(channel, 'message_to_python')
        channel.message_to_python = None
        try:
            message = Mock()
            message.errors = []
            message.decode.return_value = 'Hello'
            recv = c.receive = Mock()
            c._receive_callback(message)
            recv.assert_called_with('Hello', message)
        finally:
            channel.message_to_python = m2p

    def test_set_callbacks(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        callbacks = [lambda x, y: x, lambda x, y: x]
        consumer = Consumer(channel,
                            queue,
                            auto_declare=True,
                            callbacks=callbacks)
        self.assertEqual(consumer.callbacks, callbacks)

    def test_auto_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.consume()  # twice is a noop
        self.assertIsNot(consumer.queues[0], queue)
        self.assertTrue(consumer.queues[0].is_bound)
        self.assertTrue(consumer.queues[0].exchange.is_bound)
        self.assertIsNot(consumer.queues[0].exchange, self.exchange)

        for meth in ('exchange_declare', 'queue_declare', 'queue_bind',
                     'basic_consume'):
            self.assertIn(meth, channel)
        self.assertEqual(channel.called.count('basic_consume'), 1)
        self.assertTrue(consumer._active_tags)

        consumer.cancel_by_queue(queue.name)
        consumer.cancel_by_queue(queue.name)
        self.assertFalse(consumer._active_tags)

    def test_consumer_tag_prefix(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, tag_prefix='consumer_')
        consumer.consume()

        self.assertTrue(
            consumer._active_tags[queue.name].startswith('consumer_'), )

    def test_manual_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=False)
        self.assertIsNot(consumer.queues[0], queue)
        self.assertTrue(consumer.queues[0].is_bound)
        self.assertTrue(consumer.queues[0].exchange.is_bound)
        self.assertIsNot(consumer.queues[0].exchange, self.exchange)

        for meth in ('exchange_declare', 'queue_declare', 'basic_consume'):
            self.assertNotIn(meth, channel)

        consumer.declare()
        for meth in ('exchange_declare', 'queue_declare', 'queue_bind'):
            self.assertIn(meth, channel)
        self.assertNotIn('basic_consume', channel)

        consumer.consume()
        self.assertIn('basic_consume', channel)

    def test_consume__cancel(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.cancel()
        self.assertIn('basic_cancel', channel)
        self.assertFalse(consumer._active_tags)

    def test___enter____exit__(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        context = consumer.__enter__()
        self.assertIs(context, consumer)
        self.assertTrue(consumer._active_tags)
        res = consumer.__exit__(None, None, None)
        self.assertFalse(res)
        self.assertIn('basic_cancel', channel)
        self.assertFalse(consumer._active_tags)

    def test_flow(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.flow(False)
        self.assertIn('flow', channel)

    def test_qos(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.qos(30, 10, False)
        self.assertIn('basic_qos', channel)

    def test_purge(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4], auto_declare=True)
        consumer.purge()
        self.assertEqual(channel.called.count('queue_purge'), 4)

    def test_multiple_queues(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4])
        consumer.consume()
        self.assertEqual(channel.called.count('exchange_declare'), 4)
        self.assertEqual(channel.called.count('queue_declare'), 4)
        self.assertEqual(channel.called.count('queue_bind'), 4)
        self.assertEqual(channel.called.count('basic_consume'), 4)
        self.assertEqual(len(consumer._active_tags), 4)
        consumer.cancel()
        self.assertEqual(channel.called.count('basic_cancel'), 4)
        self.assertFalse(len(consumer._active_tags))

    def test_receive_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        received = []

        def callback(message_data, message):
            received.append(message_data)
            message.ack()
            message.payload  # trigger cache

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})

        self.assertIn('basic_ack', channel)
        self.assertIn('message_to_python', channel)
        self.assertEqual(received[0], {'foo': 'bar'})

    def test_basic_ack_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.ack()
            message.ack()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})

    def test_basic_reject(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject', channel)

    def test_basic_reject_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()
            message.reject()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject', channel)

    def test_basic_reject__requeue(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject:requeue', channel)

    def test_basic_reject__requeue_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()
            message.requeue()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject:requeue', channel)

    def test_receive_without_callbacks_raises(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        with self.assertRaises(NotImplementedError):
            consumer.receive(1, 2)

    def test_decode_error(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.channel.throw_decode_error = True

        with self.assertRaises(ValueError):
            consumer._receive_callback({'foo': 'bar'})

    def test_on_decode_error_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        thrown = []

        def on_decode_error(msg, exc):
            thrown.append((msg.body, exc))

        consumer = Consumer(channel, [b1], on_decode_error=on_decode_error)
        consumer.channel.throw_decode_error = True
        consumer._receive_callback({'foo': 'bar'})

        self.assertTrue(thrown)
        m, exc = thrown[0]
        self.assertEqual(anyjson.loads(m), {'foo': 'bar'})
        self.assertIsInstance(exc, ValueError)

    def test_recover(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.recover()
        self.assertIn('basic_recover', channel)

    def test_revive(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        channel2 = self.connection.channel()
        consumer.revive(channel2)
        self.assertIs(consumer.channel, channel2)
        self.assertIs(consumer.queues[0].channel, channel2)
        self.assertIs(consumer.queues[0].exchange.channel, channel2)

    def test__repr__(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        self.assertTrue(repr(Consumer(channel, [b1])))

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Consumer()
        p.channel = object()
        self.assertIsNone(p.connection)
Beispiel #57
0
class test_Consumer(Case):

    def setUp(self):
        self.connection = Connection(transport=Transport)
        self.connection.connect()
        self.assertTrue(self.connection.connection.connected)
        self.exchange = Exchange('foo', 'direct')

    def test_accept(self):
        a = Consumer(self.connection)
        self.assertIsNone(a.accept)
        b = Consumer(self.connection, accept=['json', 'pickle'])
        self.assertSetEqual(
            b.accept,
            set(['application/json', 'application/x-python-serialize']),
        )
        c = Consumer(self.connection, accept=b.accept)
        self.assertSetEqual(b.accept, c.accept)

    def test_enter_exit_cancel_raises(self):
        c = Consumer(self.connection)
        c.cancel = Mock(name='Consumer.cancel')
        c.cancel.side_effect = KeyError('foo')
        with c:
            pass
        c.cancel.assert_called_with()

    def test_receive_callback_accept(self):
        message = Mock(name='Message')
        message.errors = []
        callback = Mock(name='on_message')
        c = Consumer(self.connection, accept=['json'], on_message=callback)
        c.on_decode_error = None
        c.channel = Mock(name='channel')
        c.channel.message_to_python = None

        c._receive_callback(message)
        callback.assert_called_with(message)
        self.assertSetEqual(message.accept, c.accept)

    def test_accept__content_disallowed(self):
        conn = Connection('memory://')
        q = Queue('foo', exchange=self.exchange)
        p = conn.Producer()
        p.publish(
            {'complex': object()},
            declare=[q], exchange=self.exchange, serializer='pickle',
        )

        callback = Mock(name='callback')
        with conn.Consumer(queues=[q], callbacks=[callback]) as consumer:
            with self.assertRaises(consumer.ContentDisallowed):
                conn.drain_events(timeout=1)
        self.assertFalse(callback.called)

    def test_accept__content_allowed(self):
        conn = Connection('memory://')
        q = Queue('foo', exchange=self.exchange)
        p = conn.Producer()
        p.publish(
            {'complex': object()},
            declare=[q], exchange=self.exchange, serializer='pickle',
        )

        callback = Mock(name='callback')
        with conn.Consumer(queues=[q], accept=['pickle'],
                           callbacks=[callback]):
            conn.drain_events(timeout=1)
        self.assertTrue(callback.called)
        body, message = callback.call_args[0]
        self.assertTrue(body['complex'])

    def test_set_no_channel(self):
        c = Consumer(None)
        self.assertIsNone(c.channel)
        c.revive(Mock())
        self.assertTrue(c.channel)

    def test_set_no_ack(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True, no_ack=True)
        self.assertTrue(consumer.no_ack)

    def test_add_queue_when_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=True)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        self.assertIn(q, consumer.queues)
        q.declare.assert_called_with()

    def test_add_queue_when_not_auto_declare(self):
        consumer = self.connection.Consumer(auto_declare=False)
        q = Mock()
        q.return_value = q
        consumer.add_queue(q)
        self.assertIn(q, consumer.queues)
        self.assertFalse(q.declare.call_count)

    def test_consume_without_queues_returns(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = []
        self.assertIsNone(consumer.consume())

    def test_consuming_from(self):
        consumer = self.connection.Consumer()
        consumer.queues[:] = [Queue('a'), Queue('b'), Queue('d')]
        consumer._active_tags = {'a': 1, 'b': 2}

        self.assertFalse(consumer.consuming_from(Queue('c')))
        self.assertFalse(consumer.consuming_from('c'))
        self.assertFalse(consumer.consuming_from(Queue('d')))
        self.assertFalse(consumer.consuming_from('d'))
        self.assertTrue(consumer.consuming_from(Queue('a')))
        self.assertTrue(consumer.consuming_from(Queue('b')))
        self.assertTrue(consumer.consuming_from('b'))

    def test_receive_callback_without_m2p(self):
        channel = self.connection.channel()
        c = channel.Consumer()
        m2p = getattr(channel, 'message_to_python')
        channel.message_to_python = None
        try:
            message = Mock()
            message.errors = []
            message.decode.return_value = 'Hello'
            recv = c.receive = Mock()
            c._receive_callback(message)
            recv.assert_called_with('Hello', message)
        finally:
            channel.message_to_python = m2p

    def test_set_callbacks(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        callbacks = [lambda x, y: x,
                     lambda x, y: x]
        consumer = Consumer(channel, queue, auto_declare=True,
                            callbacks=callbacks)
        self.assertEqual(consumer.callbacks, callbacks)

    def test_auto_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.consume()  # twice is a noop
        self.assertIsNot(consumer.queues[0], queue)
        self.assertTrue(consumer.queues[0].is_bound)
        self.assertTrue(consumer.queues[0].exchange.is_bound)
        self.assertIsNot(consumer.queues[0].exchange, self.exchange)

        for meth in ('exchange_declare',
                     'queue_declare',
                     'queue_bind',
                     'basic_consume'):
            self.assertIn(meth, channel)
        self.assertEqual(channel.called.count('basic_consume'), 1)
        self.assertTrue(consumer._active_tags)

        consumer.cancel_by_queue(queue.name)
        consumer.cancel_by_queue(queue.name)
        self.assertFalse(consumer._active_tags)

    def test_manual_declare(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=False)
        self.assertIsNot(consumer.queues[0], queue)
        self.assertTrue(consumer.queues[0].is_bound)
        self.assertTrue(consumer.queues[0].exchange.is_bound)
        self.assertIsNot(consumer.queues[0].exchange, self.exchange)

        for meth in ('exchange_declare',
                     'queue_declare',
                     'basic_consume'):
            self.assertNotIn(meth, channel)

        consumer.declare()
        for meth in ('exchange_declare',
                     'queue_declare',
                     'queue_bind'):
            self.assertIn(meth, channel)
        self.assertNotIn('basic_consume', channel)

        consumer.consume()
        self.assertIn('basic_consume', channel)

    def test_consume__cancel(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.consume()
        consumer.cancel()
        self.assertIn('basic_cancel', channel)
        self.assertFalse(consumer._active_tags)

    def test___enter____exit__(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        context = consumer.__enter__()
        self.assertIs(context, consumer)
        self.assertTrue(consumer._active_tags)
        res = consumer.__exit__(None, None, None)
        self.assertFalse(res)
        self.assertIn('basic_cancel', channel)
        self.assertFalse(consumer._active_tags)

    def test_flow(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.flow(False)
        self.assertIn('flow', channel)

    def test_qos(self):
        channel = self.connection.channel()
        queue = Queue('qname', self.exchange, 'rkey')
        consumer = Consumer(channel, queue, auto_declare=True)
        consumer.qos(30, 10, False)
        self.assertIn('basic_qos', channel)

    def test_purge(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4], auto_declare=True)
        consumer.purge()
        self.assertEqual(channel.called.count('queue_purge'), 4)

    def test_multiple_queues(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        b2 = Queue('qname2', self.exchange, 'rkey')
        b3 = Queue('qname3', self.exchange, 'rkey')
        b4 = Queue('qname4', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1, b2, b3, b4])
        consumer.consume()
        self.assertEqual(channel.called.count('exchange_declare'), 4)
        self.assertEqual(channel.called.count('queue_declare'), 4)
        self.assertEqual(channel.called.count('queue_bind'), 4)
        self.assertEqual(channel.called.count('basic_consume'), 4)
        self.assertEqual(len(consumer._active_tags), 4)
        consumer.cancel()
        self.assertEqual(channel.called.count('basic_cancel'), 4)
        self.assertFalse(len(consumer._active_tags))

    def test_receive_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        received = []

        def callback(message_data, message):
            received.append(message_data)
            message.ack()
            message.payload     # trigger cache

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})

        self.assertIn('basic_ack', channel)
        self.assertIn('message_to_python', channel)
        self.assertEqual(received[0], {'foo': 'bar'})

    def test_basic_ack_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.ack()
            message.ack()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})

    def test_basic_reject(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject', channel)

    def test_basic_reject_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.reject()
            message.reject()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject', channel)

    def test_basic_reject__requeue(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()

        consumer.register_callback(callback)
        consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject:requeue', channel)

    def test_basic_reject__requeue_twice(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])

        def callback(message_data, message):
            message.requeue()
            message.requeue()

        consumer.register_callback(callback)
        with self.assertRaises(MessageStateError):
            consumer._receive_callback({'foo': 'bar'})
        self.assertIn('basic_reject:requeue', channel)

    def test_receive_without_callbacks_raises(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        with self.assertRaises(NotImplementedError):
            consumer.receive(1, 2)

    def test_decode_error(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.channel.throw_decode_error = True

        with self.assertRaises(ValueError):
            consumer._receive_callback({'foo': 'bar'})

    def test_on_decode_error_callback(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        thrown = []

        def on_decode_error(msg, exc):
            thrown.append((msg.body, exc))

        consumer = Consumer(channel, [b1], on_decode_error=on_decode_error)
        consumer.channel.throw_decode_error = True
        consumer._receive_callback({'foo': 'bar'})

        self.assertTrue(thrown)
        m, exc = thrown[0]
        self.assertEqual(anyjson.loads(m), {'foo': 'bar'})
        self.assertIsInstance(exc, ValueError)

    def test_recover(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        consumer.recover()
        self.assertIn('basic_recover', channel)

    def test_revive(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        consumer = Consumer(channel, [b1])
        channel2 = self.connection.channel()
        consumer.revive(channel2)
        self.assertIs(consumer.channel, channel2)
        self.assertIs(consumer.queues[0].channel, channel2)
        self.assertIs(consumer.queues[0].exchange.channel, channel2)

    def test__repr__(self):
        channel = self.connection.channel()
        b1 = Queue('qname1', self.exchange, 'rkey')
        self.assertTrue(repr(Consumer(channel, [b1])))

    def test_connection_property_handles_AttributeError(self):
        p = self.connection.Consumer()
        p.channel = object()
        self.assertIsNone(p.connection)
Beispiel #58
0
class Amqp(Thread):
    def __init__(
        self,
        host="localhost",
        port=5672,
        userid="guest",
        password="******",
        virtual_host="canopsis",
        exchange_name="canopsis",
        logging_name="Amqp",
        logging_level=INFO,
        read_config_file=True,
        auto_connect=True,
        on_ready=None,
        max_retries=5,
    ):
        super(Amqp, self).__init__()

        self.logger = getLogger(logging_name)

        self.host = host
        self.port = port
        self.userid = userid
        self.password = password
        self.virtual_host = virtual_host
        self.exchange_name = exchange_name
        self.logging_level = logging_level

        if read_config_file:
            self.read_config("amqp")

        self.amqp_uri = "amqp://{0}:{1}@{2}:{3}/{4}".format(
            self.userid, self.password, self.host, self.port, self.virtual_host
        )

        self.logger.setLevel(logging_level)

        # Event sent try count before event drop in case of connection problem
        if max_retries != 5:
            self.logger.info(u"Custom retries value : {} {}".format(max_retries, type(max_retries)))
        self.max_retries = max_retries

        self.exchange_name_events = exchange_name + ".events"
        self.exchange_name_alerts = exchange_name + ".alerts"
        self.exchange_name_incidents = exchange_name + ".incidents"

        self.chan = None
        self.conn = None
        self.connected = False
        self.on_ready = on_ready

        self.RUN = True

        self.exchanges = {}

        self.queues = {}

        self.paused = False

        self.connection_errors = (ConnectionError, error, IOError, OSError)

        # Create exchange
        self.logger.debug("Create exchanges object")
        for exchange_name in [
            self.exchange_name,
            self.exchange_name_events,
            self.exchange_name_alerts,
            self.exchange_name_incidents,
        ]:
            self.logger.debug(u" + {0}".format(exchange_name))
            self.get_exchange(exchange_name)

        if auto_connect:
            self.connect()

        self.logger.debug("Object canamqp initialized")

    def run(self):
        self.logger.debug("Start thread ...")
        reconnect = False

        while self.RUN:

            self.connect()

            if self.connected:
                self.init_queue(reconnect=reconnect)

                self.logger.debug("Drain events ...")
                while self.RUN:
                    try:
                        if not self.paused:
                            self.conn.drain_events(timeout=0.5)
                        else:
                            sleep(0.5)

                    except timeout:
                        pass

                    except self.connection_errors as err:
                        self.logger.error(u"Connection error ! ({})".format(err))
                        break

                    except Exception as err:
                        self.logger.error(u"Error: {} ({})".format(err, type(err)))
                        print_exc(file=stdout)
                        break

                self.disconnect()

            if self.RUN:
                self.logger.error("Connection lost, try to reconnect in few seconds ...")
                reconnect = True
                self.wait_connection(timeout=5)

        self.logger.debug("End of thread ...")

    def stop(self):
        self.logger.debug("Stop thread ...")
        self.RUN = False

    def connect(self):
        if not self.connected:
            self.logger.info("Connect to AMQP Broker (%s:%s)" % (self.host, self.port))

            self.conn = Connection(self.amqp_uri)

            try:
                self.logger.debug(" + Connect")
                self.conn.connect()
                self.logger.info("Connected to AMQP Broker.")
                self.producers = pools.Producers(limit=10)
                self.connected = True
            except Exception as err:
                self.conn.release()
                self.logger.error(u"Impossible to connect ({})".format(err))

            if self.connected:
                self.logger.debug(" + Open channel")
                try:
                    self.chan = self.conn.channel()

                    self.logger.debug("Channel openned. Ready to send messages")

                    try:
                        # Declare exchange
                        self.logger.debug("Declare exchanges")
                        for exchange_name in self.exchanges:
                            self.logger.debug(u" + {}".format(exchange_name))
                            self.exchanges[exchange_name](self.chan).declare()
                    except Exception as err:
                        self.logger.error(u"Impossible to declare exchange ({})".format(err))

                except Exception as err:
                    self.logger.error(err)
        else:
            self.logger.debug("Already connected")

    def get_exchange(self, name):
        if name:
            try:
                return self.exchanges[name]
            except:
                if name == "amq.direct":
                    self.exchanges[name] = Exchange(name, "direct", durable=True)
                else:
                    self.exchanges[name] = Exchange(name, "topic", durable=True, auto_delete=False)
                return self.exchanges[name]
        else:
            return None

    def init_queue(self, reconnect=False):
        if self.queues:
            self.logger.debug("Init queues")
            for queue_name in self.queues.keys():
                self.logger.debug(u" + {}".format(queue_name))
                qsettings = self.queues[queue_name]

                if not qsettings["queue"]:
                    self.logger.debug("   + Create queue")

                    # copy list
                    routing_keys = list(qsettings["routing_keys"])
                    routing_key = None

                    if len(routing_keys):
                        routing_key = routing_keys[0]
                        routing_keys = routing_keys[1:]

                    exchange = self.get_exchange(qsettings["exchange_name"])

                    if qsettings["exchange_name"] == "amq.direct" and not routing_key:
                        routing_key = queue_name

                    self.logger.debug(
                        (u"exchange: '{}', exclusive: {}," + " auto_delete: {},no_ack: {}").format(
                            qsettings["exchange_name"],
                            qsettings["exclusive"],
                            qsettings["auto_delete"],
                            qsettings["no_ack"],
                        )
                    )
                    qsettings["queue"] = Queue(
                        queue_name,
                        exchange=exchange,
                        routing_key=routing_key,
                        exclusive=qsettings["exclusive"],
                        auto_delete=qsettings["auto_delete"],
                        no_ack=qsettings["no_ack"],
                        channel=self.conn.channel(),
                    )

                    qsettings["queue"].declare()

                    if len(routing_keys):
                        self.logger.debug(" + Bind on all routing keys")
                        for routing_key in routing_keys:
                            self.logger.debug(" + routing_key: '{}'".format(routing_key))
                            try:
                                qsettings["queue"].bind_to(exchange=exchange, routing_key=routing_key)
                            except:
                                self.logger.error(u"You need upgrade your Kombu version ({})".format(__version__))

                if not qsettings["consumer"] or reconnect:
                    self.logger.debug("   + Create Consumer")
                    qsettings["consumer"] = self.conn.Consumer(qsettings["queue"], callbacks=[qsettings["callback"]])

                self.logger.debug("   + Consume queue")
                qsettings["consumer"].consume()

            if self.on_ready:
                self.on_ready()

    def add_queue(
        self, queue_name, routing_keys, callback, exchange_name=None, no_ack=True, exclusive=False, auto_delete=True
    ):

        c_routing_keys = []

        if not isinstance(routing_keys, list):
            if isinstance(routing_keys, basestring):
                c_routing_keys = [routing_keys]
        else:
            c_routing_keys = routing_keys

        if not exchange_name:
            exchange_name = self.exchange_name

        self.queues[queue_name] = {
            "queue": False,
            "consumer": False,
            "queue_name": queue_name,
            "routing_keys": c_routing_keys,
            "callback": callback,
            "exchange_name": exchange_name,
            "no_ack": no_ack,
            "exclusive": exclusive,
            "auto_delete": auto_delete,
        }

    def publish(
        self,
        msg,
        routing_key,
        exchange_name=None,
        serializer="json",
        compression=None,
        content_type=None,
        content_encoding=None,
    ):

        operation_success = False
        retries = 0

        while not operation_success and retries < self.max_retries:
            retries += 1

            if self.connected:

                if not exchange_name:
                    exchange_name = self.exchange_name

                with self.producers[self.conn].acquire(block=True) as producer:
                    try:
                        _msg = msg.copy()

                        Amqp._clean_msg_for_serialization(_msg)

                        producer.publish(
                            _msg,
                            serializer=serializer,
                            compression=compression,
                            routing_key=routing_key,
                            exchange=self.get_exchange(exchange_name),
                        )

                        self.logger.debug("publish {} in exchange {}".format(routing_key, exchange_name))

                        operation_success = True

                    except Exception as e:
                        self.logger.error(u" + Impossible to send {}".format(e))
                        self.disconnect()
                        self.connect()
            else:
                self.logger.error("Not connected ... try reconnecting")
                self.connect()

            if not operation_success:
                # Event and it's information are buffered until next send retry
                self.logger.info(u"Retry count {}".format(retries))

        if not operation_success:
            # Event and it's information are buffered until next send retry
            self.logger.error(u"Too much retries for event {}, give up".format(routing_key))

    @staticmethod
    def _clean_msg_for_serialization(msg):
        from bson import objectid

        for key in msg:
            if isinstance(msg[key], objectid.ObjectId):
                msg[key] = str(msg[key])

    def cancel_queues(self):
        if self.connected:
            for queue_name in self.queues.keys():
                if self.queues[queue_name]["consumer"]:
                    self.logger.debug(u" + Cancel consumer on {}".format(queue_name))
                    try:
                        self.queues[queue_name]["consumer"].cancel()
                    except:
                        pass

                    del (self.queues[queue_name]["consumer"])
                    self.queues[queue_name]["consumer"] = False
                    del (self.queues[queue_name]["queue"])
                    self.queues[queue_name]["queue"] = False

    def disconnect(self):
        if self.connected:
            self.logger.info("Disconnect from AMQP Broker")

            self.cancel_queues()

            for exchange in self.exchanges:
                del exchange
            self.exchanges = {}

            try:
                pools.reset()
            except Exception as err:
                self.logger.error(u"Impossible to reset kombu pools: {} ({})".format(err, type(err)))

            try:
                self.conn.release()
                del self.conn
            except Exception as err:
                self.logger.error(u"Impossible to release connection: {} ({})".format(err, type(err)))

            self.connected = False

    def wait_connection(self, timeout=5):
        i = 0
        while self.RUN and not self.connected and i < (timeout * 2):
            try:
                sleep(0.5)
            except:
                pass
            i += 1

    def read_config(self, name):

        filename = join(sys_prefix, "etc", u"{0}.conf".format(name))

        import ConfigParser

        self.config = ConfigParser.RawConfigParser()

        try:
            self.config.read(filename)

            section = "master"

            self.host = self.config.get(section, "host")
            self.port = self.config.getint(section, "port")
            self.userid = self.config.get(section, "userid")
            self.password = self.config.get(section, "password")
            self.virtual_host = self.config.get(section, "virtual_host")
            self.exchange_name = self.config.get(section, "exchange_name")

        except Exception as err:
            self.logger.error(u"Can't to load configurations ({}), use default ...".format(err))

    def __del__(self):
        self.stop()
Beispiel #59
0
from kombu import Connection

connection = Connection('amqp://*****:*****@localhost:5672//')

connection.connect()
#check whether connected boolean
connection.connected
connection.close()
#better practice, releases resource if in a connection pool else close
connection.release()