コード例 #1
0
ファイル: __init__.py プロジェクト: azazel75/zato
class BaseAMQPConnection(BaseConnection):
    """ An object which does an actual job of (re-)connecting to the the AMQP broker.
    Concrete subclasses implement either listening or publishing features.
    """
    def __init__(self, conn_params, item_name, properties=None):
        super(BaseAMQPConnection, self).__init__()
        self.conn_params = conn_params
        self.item_name = item_name
        self.properties = properties
        self.conn = None
        self.channel = None
        self.reconnect_exceptions = (TypeError, EnvironmentError)

    def _start(self):
        self.conn = SelectConnection(self.conn_params, self._on_connected)
        self.conn.ioloop.start()
        
    def _close(self):
        """ Actually close the connection.
        """
        if self.conn:
            try:
                self.conn.close()
            except socket.error, e:
                if e.errno != errno.EBADF:
                    # EBADF meant we actually had a connection but it was unusable (like the credentials were incorrect)
                    raise
コード例 #2
0
    def connect(self, forever=False):
        name = self.name
        while True:
            try:
                connection = SelectConnection(
                    self.parameters, self.on_connected)
                log.debug('%s connected', name)
            except Exception:
                if not forever:
                    raise
                log.warning('%s cannot connect', name, exc_info=True)
                time.sleep(10)
                continue

            try:
                connection.ioloop.start()
            finally:
                try:
                    connection.close()
                    connection.ioloop.start() # allow connection to close
                except Exception:
                    pass

            if not forever:
                break
コード例 #3
0
ファイル: messaging.py プロジェクト: sunetos/anode
def testnb():
    node = NodeNB()
    #ch = node.channel(('amq.direct', 'foo'), TestServer)
    ch = node.channel(TestServer)
    #ch = node.channel(TestClient)
    conn_parameters = ConnectionParameters()
    connection = SelectConnection(conn_parameters , node.on_connection_open)
    # Loop until CTRL-C
    try:
        # Start our blocking loop
        connection.ioloop.start()

    except KeyboardInterrupt:

        # Close the connection
        connection.close()

        # Loop until the connection is closed
        connection.ioloop.start()
コード例 #4
0
ファイル: server.py プロジェクト: JustOnce/BlogSamples
def simple_server(ca_certs, keyfile, certfile, host_name, use_ssl):
    host = host_name
    if use_ssl:
        ssl_opts = {'ca_certs': ca_certs,
                    'keyfile': keyfile,
                    'certfile': certfile,
                    'cert_reqs': ssl.CERT_REQUIRED}
        port = 5671
    else:
        ssl_opts = None
        port = 5672
    parameters = ConnectionParameters(host, port,
        ssl=use_ssl, ssl_options=ssl_opts)
    connection = SelectConnection(parameters, on_connected)

    # Loop until CTRL-C
    try:
        # Start our blocking loop
        connection.ioloop.start()
    except KeyboardInterrupt:
        # Close the connection
        connection.close()
        # Loop until the connection is closed
        connection.ioloop.start()
コード例 #5
0
ファイル: amqpclient.py プロジェクト: shuaizhang15/krproject
                              routing_key="krqueue",
                              body=jsonmsg,
                              properties=properties)

        print "demo_send:" + jsonmsg

    # Close our connection
    print "Closing client"
    connection.close()


if __name__ == '__main__':
    pika.log.setup(level=pika.log.INFO)

    # Connect to RabbitMQ
    host = (len(sys.argv) > 1) and sys.argv[1] or '127.0.0.1'
    connection = SelectConnection(ConnectionParameters(host),
                                  on_connected)
    # Loop until CTRL-C
    try:
        # Start our blocking loop
        connection.ioloop.start()

    except KeyboardInterrupt:

        # Close the connection
        connection.close()

        # Loop until the connection is closed
        connection.ioloop.stop()
コード例 #6
0
ファイル: demo_send.py プロジェクト: pierremarc/pika
                              routing_key="test",
                              body=message,
                              properties=properties)

        print "demo_send: Sent %s" % message

    # Close our connection
    print "demo_send: Closing"
    connection.close()


if __name__ == '__main__':
    pika.log.setup(level=pika.log.INFO)

    # Connect to RabbitMQ
    host = (len(sys.argv) > 1) and sys.argv[1] or '127.0.0.1'
    connection = SelectConnection(ConnectionParameters(host),
                                  on_connected)
    # Loop until CTRL-C
    try:
        # Start our blocking loop
        connection.ioloop.start()

    except KeyboardInterrupt:

        # Close the connection
        connection.close()

        # Loop until the connection is closed
        connection.ioloop.start()
コード例 #7
0
ファイル: router.py プロジェクト: psawaya/notif
class RouterServer(object):
    """Validates and routes notifications.
    
    This acts as a separate server used only for production systems.
    In a development environment, the post office performs the validation
    itself, however this does not allow it to scale in situations where
    a large spike of requests come in (as the requests take longer to
    complete when validation is performed). Thus in production the post
    office simply dumps messages into queue which are then consumed, 
    validated, and then routed to their destination.

    """

    def __init__(self, config):
        self.delivery_conn = None
        self.delivery_channel = None 
        self.notifs_conn = None
        self.notifs_channel = None
        
        # Extract configuration
        self.broker_username = config['broker.username']
        self.broker_password = config['broker.password']
        self.broker_host = config['broker.host']
        self.broker_amqp_port = config['broker.amqp_port']
        self.broker_http_port = config['broker.http_port']
        self.broker_vhost = config['broker.vhost']
        self.incoming_exchange_name = config['broker.incoming_exchange_name']
        self.notifs_queue_name = config['broker.notifications_queue_name']

        # Create connection parameters object for easy reuse
        self.conn_params = pika.ConnectionParameters(
            credentials=pika.PlainCredentials(
                self.broker_username,
                self.broker_password,
            ),
            host=self.broker_host,
            port=self.broker_amqp_port,
            virtual_host=self.broker_vhost,
        )
        
        self.notifs_conn = SelectConnection(
            self.conn_params,
            self.on_notifs_connected,
        )

    @wsgify
    def __call__(self, request):
        """Allows router to be called directly by POST Office to perform
        validation. Intended to simplify development -- SHOULD NOT be 
        used in a production system.

        """
        try:
            self.process_notification(request.body)
        except KeyError as kerr:
            raise HTTPBadRequest()
        except Exception as ex:
            raise HTTPInternalServerError()

        return HTTPAccepted()
        
    # XXX: Ugh...why must Pika be so difficult with multiple connections?
    def start(self, blocking=True):
        #Thread(target=self.delivery_conn.ioloop.start).start()

        if blocking:
            self.notifs_conn.ioloop.start()
        else:
            Thread(target=self.notifs_conn.ioloop.start).start()

    def shutdown(self):
        self.delivery_channel.close()
        self.notifs_channel.close()
        self.delivery_conn.close()
        self.notifs_conn.close()

        # Loop until everything shuts down
        self.notifs_conn.ioloop.start()

    def on_delivery_connected(self, connection):
        connection.channel(self.on_delivery_channel_open)

    def on_delivery_channel_open(self, channel):
        self.delivery_channel = channel

    def on_notifs_connected(self, connection):
        connection.channel(self.on_notifications_channel_open)

        # TODO: Figure out how to get 2 connections working in Pika.
        # This is a hack for now, since we know we only have one broker.
        self.on_delivery_connected(connection)

    def on_notifications_channel_open(self, channel):
        self.notifs_channel = channel
        channel.queue_declare(
            queue=self.notifs_queue_name,
            durable=False,
            exclusive=False,
            auto_delete=False,
            callback=self.on_notifications_queue_declared,
        )

    def on_notifications_queue_declared(self, frame):
        self.notifs_channel.basic_consume(
            self.handle_notification,
            queue=self.notifs_queue_name,
            no_ack=True,
        )

    def handle_notification(self, channel, method, properties, body):
        print "Received notification"

        try:
            self.process_notification(body)
            print "Processed notification"
        except Exception as ex:
            print "Error processing notification: %r" % ex
                
    def process_notification(self, message):
        """Processes a message consumed from the incoming queue."""

        print " [x] %s" % message

        # Make sure JSON is valid
        notif = json.loads(message)

        if 'token' not in notif:
            raise KeyError('Notification key "token" not found.')

        if 'type' not in notif:
            # No type specified; use default
            notif['type'] = "text"

        if 'timestamp' not in notif:
            # No timestamp specified; create one
            notif['timestamp'] = int(time.time())

        if 'ttl' not in notif:
            # No TTL specified; create one (30 days)
            notif['ttl'] = 30*24*60*60

        if 'payload' not in notif:
            raise KeyError('Notification key "payload" not found.')

        if 'ciphertext' not in notif['payload']:
            raise KeyError('Notification key "payload.ciphertext" not found.')

        try:
            # Assert exchange is declared
            self.delivery_channel.exchange_declare(
                exchange=self.incoming_exchange_name,
                durable=True,
                type='fanout'
            )

            # Python's JSON parser assumes everything is Unicode, and Pika
            # uses the "+" operator when it shouldn't.
            token = notif['token'].encode('ascii')

            self.delivery_channel.basic_publish(
                exchange=self.incoming_exchange_name,
                routing_key=token,
                body=message
            )

            print "Notification routed to user exchange"

        except Exception as ex:
            # TODO: Either put the message back in the incoming queue, or send
            # a NACK to the broker if we're going to do ACK/NACK crap
            raise ex
コード例 #8
0
ファイル: amqp.py プロジェクト: Smartaleck/synapse-agent
class Amqp(object):
    def __init__(self, conf):

        # RabbitMQ general options
        self.cacertfile = conf['cacertfile']
        self.certfile = conf['certfile']
        self.exchange = conf['exchange']
        self.status_exchange = conf['status_exchange']
        self.fail_if_no_peer_cert = conf['fail_if_no_peer_cert']
        self.heartbeat = conf['heartbeat']
        self.host = conf['host']
        self.keyfile = conf['keyfile']
        self.password = conf['password']
        self.port = conf['port']
        self.ssl_port = conf['ssl_port']
        self.queue = conf['uuid']
        self.retry_timeout = conf['retry_timeout']
        self.ssl_auth = conf['ssl_auth']
        self.use_ssl = conf['use_ssl']
        self.username = conf['username']
        self.vhost = conf['vhost']

        # Connection and channel initialization
        self.connection = None
        self.channel = None

        # Plain credentials
        credentials = PlainCredentials(self.username, self.password)
        pika_options = {'host': self.host,
                        'port': self.port,
                        'virtual_host': self.vhost,
                        'credentials': credentials}

        # SSL options
        if self.use_ssl:
            pika_options['ssl'] = True
            pika_options['port'] = self.ssl_port
            if self.ssl_auth:
                pika_options['credentials'] = ExternalCredentials()
                pika_options['ssl_options'] = {
                    'ca_certs': self.cacertfile,
                    'certfile': self.certfile,
                    'keyfile': self.keyfile,
                    'cert_reqs': CERT_REQUIRED
                }

        if self.heartbeat:
            pika_options['heartbeat'] = self.heartbeat

        self.parameters = None

        try:
            self.parameters = pika.ConnectionParameters(**pika_options)
        except TypeError as err:
            self.logger.debug(err)
            # Let's be compatible with original pika version (no integer for
            # heartbeats and no ssl.
            self.logger.warning("Wrong pika lib version, won't use ssl.")
            pika_options['heartbeat'] = True
            if self.use_ssl:
                self.use_ssl = False
                pika_options['port'] = self.port
                del pika_options['ssl']
                if self.ssl_auth:
                    self.ssl_auth = False
                    del pika_options['ssl_options']

            self.parameters = pika.ConnectionParameters(**pika_options)

    def connect(self):
        SelectPoller.TIMEOUT = .1
        self.connection = SelectConnection(self.parameters, self.on_connected)
        self.connection.ioloop.start()

    def close(self, amqperror=False):
        if (self.connection and not self.connection.closing
            and not self.connection.closed):

            self.logger.debug("Closing connection")
            self.connection.close()
            #self.connection.ioloop.start()

    def on_remote_close(self, code, text):
        self.logger.debug("Remote channel close, code %d" % code)
        time.sleep(2)
        if code != 200:
            self.close()
            raise AmqpError(text)

    def on_connection_closed(self, frame):
        self.connection.ioloop.stop()

    def on_connected(self, connection):
        self.connection = connection
        self.connection.add_on_close_callback(self.on_connection_closed)
        self.connection.channel(self.on_channel_open)
コード例 #9
0
ファイル: newsfeed_maggot.py プロジェクト: lordke/RssFeedMQ
class NewsFeedMaggot(Thread):
    def __init__(self):
        super(NewsFeedMaggot, self).__init__()
        self.feeds = []
        self.update_track_dict()
        self.processfeed = ProcessFeed()
        self.channel = None
        self.connection = None
        self.alive = False
        self.stop_flag = False
        self.r = None
        self.r_last_touched = datetime.now()

    def update_track_dict(self):
        global DB_CONN
        try:
            LOGGER.info("Obtaining track from postgre")
            if DB_CONN is None:
                connect_pg()
            # Get all ids from "feedjack_track"
            track_ids = []
            cursor = DB_CONN.cursor(cursor_factory=psycopg2.extras.DictCursor)
            cursor.execute("SELECT id FROM feedjack_track")
            results = cursor.fetchall()
            for result in results:
                track_ids.append(result['id'])
            # Get "trackedphrase" for each "track"
            for track_id in track_ids:
                TRACK_DICT[track_id] = []
                cursor.execute("SELECT id, name, mode " \
                               "FROM feedjack_trackedphrase " \
                               "WHERE track_id=%s", (track_id,))
                results = cursor.fetchall()
                for result in results:
                    TRACK_DICT[track_id].append({
                        'trackedphrase_id':
                        result['id'],
                        'name':
                        result['name'],
                        'mode':
                        result['mode']
                    })
            LOGGER.info("Obtaining trackedphrase completed")
            #pprint(TRACK_DICT)
        except:
            DB_CONN.rollback()
            LOGGER.info(sys.exc_info())

    def post_init(self):
        #初始化 新建RabbitMQ 队列和exchange并绑定(2个)
        LOGGER.info('Initializing a FeedProcessor')
        #self.feedprocessor.post_init()
        LOGGER.info('Initializing a FeedProcessor completed')
        try:
            LOGGER.info('Opening a connection')
            #self.dispatcher = Dispatcher(self.options)
            self.connection = SelectConnection(
                parameters=settings.pika_parameters,
                on_open_callback=self.on_connection_open)
            try:
                LOGGER.info('Starting ioloop')
                self.connection.ioloop.start()
            except KeyboardInterrupt:
                # Gracefully close the connection
                self.connection.close()
                # Loop until we're fully closed, will stop on its own
                self.connection.ioloop.start()
        except:
            (etype, eobj, etb) = sys.exc_info()
            print traceback.format_exception(etype, eobj, etb)

    def on_connection_open(self, unused_connection):
        LOGGER.info('Opening a connection completed')
        self.open_channel()

    def open_channel(self):
        LOGGER.info('Opening a channel')
        self.connection.channel(on_open_callback=self.on_channel_open)

    def on_channel_open(self, new_channel):
        LOGGER.info('Opening a channel completed')
        self.channel = new_channel
        self.declare_exchange()
        self.declare_exchange2()

    def declare_exchange(self):
        LOGGER.info('Declaring an exchange')
        self.channel.exchange_declare(
            exchange=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_NAME,
            exchange_type=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_TYPE,
            passive=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_PASSIVE,
            durable=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_DURABLE,
            auto_delete=settings.
            RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_AUTO_DELETE,
            internal=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_INTERNAL,
            nowait=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_NOWAIT,
            arguments=None,  # Custom key/value pair arguments for the exchange
            callback=self.on_exchange_declared
        )  # Call this method on Exchange.DeclareOk

    def on_exchange_declared(self, unused_frame):
        LOGGER.info('Declaring an exchange completed')
        self.declare_queue()

    def declare_queue(self):
        LOGGER.info('Declaring a queue')
        self.channel.queue_declare(
            self.on_queue_declared,
            settings.RABBITMQ_NEWSFEED_RAW_FEED_QUEUE_NAME)

    def on_queue_declared(self, method_frame):
        LOGGER.info('Declaring a queue completed')
        self.bind_queue()

    def bind_queue(self):
        LOGGER.info('Binding a queue')
        self.channel.queue_bind(
            callback=self.on_queue_binded,
            queue=settings.RABBITMQ_NEWSFEED_RAW_FEED_QUEUE_NAME,
            exchange=settings.RABBITMQ_NEWSFEED_RAW_FEED_EXCHANGE_NAME,
            routing_key=settings.RABBITMQ_NEWSFEED_RAW_FEED_ROUTING_KEY)

    def on_queue_binded(self, frame):
        LOGGER.info('Binding a queue completed')
        # Start the thread's activity
        self.start()

    ###############################
    def declare_exchange2(self):
        LOGGER.info('Declaring an exchange2')
        self.channel.exchange_declare(
            exchange=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NAME,
            exchange_type=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_TYPE,
            passive=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_PASSIVE,
            durable=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_DURABLE,
            auto_delete=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_AUTO_DELETE,
            internal=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_INTERNAL,
            nowait=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NOWAIT,
            arguments=None,  # Custom key/value pair arguments for the exchange
            callback=self.on_exchange_declared2
        )  # Call this method on Exchange.DeclareOk

    def on_exchange_declared2(self, frame):
        LOGGER.info('Declaring an exchange2 completed')
        self.declare_queue2()

    def declare_queue2(self):
        LOGGER.info('Declaring a queue2')
        self.channel.queue_declare(
            callback=self.on_queue_declared2,
            queue=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NAME,
            passive=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_PASSIVE,
            durable=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_DURABLE,
            exclusive=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_EXCLUSIVE,
            auto_delete=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_AUTO_DELETE,
            nowait=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NOWAIT,
            arguments=None)

    def on_queue_declared2(self, method_frame):
        LOGGER.info('Declaring a queue2 completed')
        self.bind_queue2()

    def bind_queue2(self):
        LOGGER.info('Binding a queue2')
        self.channel.queue_bind(
            callback=self.on_queue_binded2,
            queue=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NAME,
            exchange=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NAME,
            routing_key=settings.RABBITMQ_NEWSFEED_ENTRY_ROUTING_KEY)

    def on_queue_binded2(self, frame):
        LOGGER.info('Binding a queue completed on 2')

    def on_message(self, channel, basic_deliver, properties, body):
        """Invoked by pika when a message is delivered from RabbitMQ. The
        channel is passed for your convenience. The basic_deliver object that
        is passed in carries the exchange, routing key, delivery tag and
        a redelivered flag for the message. The properties passed in is an
        instance of BasicProperties with the message properties and the body
        is the message that was sent

        收到消息message,processfeed 类处理成单个postlist并发送给websocket

        :param pika.channel.Channel channel: The channel object
        :param pika.Spec.Basic.Deliver: basic_deliver method
        :param pika.Spec.BasicProperties: properties
        :param str|unicode body: The message body
        """
        LOGGER.info('Received message # %s from %s',
                    basic_deliver.delivery_tag, properties.app_id)
        self.ack_message(basic_deliver.delivery_tag)

        try:
            data = JSON_DECODER.decode(body)
            #pprint(data)
            (entries_status, post_list) = self.processfeed.process(data)
            for post in post_list:
                LOGGER.info('Publishing data (post id: %d) to %s',
                            post['post_id'],
                            settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NAME)
                json_data = JSON_ENCODER.encode(post)
                self.channel.basic_publish(
                    exchange=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NAME,
                    routing_key=settings.RABBITMQ_NEWSFEED_ENTRY_ROUTING_KEY,
                    body=json_data)
                LOGGER.info('Publishing data completed')

        except simplejson.JSONDecodeError:
            LOGGER.info(sys.exc_info())
        #except simplejson.JSONEncodeError:
        #    LOGGER.info(sys.exc_info())

    def ack_message(self, delivery_tag):
        """Acknowledge the message delivery from RabbitMQ by sending a
        Basic.Ack RPC method for the delivery tag.

        :param int delivery_tag: The delivery tag from the Basic.Deliver frame
        """
        LOGGER.info('Acknowledging message %s', delivery_tag)
        self.channel.basic_ack(delivery_tag)

    def run(self):
        #设置channel.basic_consume MQ消息接收
        LOGGER.info('Start to consume message from queue')
        self.channel.basic_consume(
            consumer_callback=self.on_message,
            queue=settings.RABBITMQ_NEWSFEED_RAW_FEED_QUEUE_NAME,
            no_ack=
            False,  # Set to True means tell the broker to not expect a response
            exclusive=
            False,  # Set to True means don't allow other consumers on the queue
            consumer_tag=None)  # Specify your own consumer tag
コード例 #10
0
ファイル: newsfeed_opinion.py プロジェクト: lordke/RssFeedMQ
class NewsFeedOpinion(Thread):
    def __init__(self):
        super(NewsFeedOpinion, self).__init__()
        self.feeds = []
        self.update_sentimentwords()
        self.channel = None
        self.connection = None
        self.processopinion = ProcessOpinion()
        self.alive = False
        self.stop_flag = False
        self.r = None
        self.r_last_touched = datetime.now()

    def update_sentimentwords(self):
        global NEG_WORDS
        global DB_CONN
        try:
            LOGGER.info("Obtaining sentiment word list from postgre")
            if DB_CONN is None:
                connect_pg()
            cursor = DB_CONN.cursor()
            cursor.execute(
                "SELECT name FROM sentidict_sentimentword WHERE mode='2'")
            results = cursor.fetchall()
            for result in results:
                NEG_WORDS.append(str(result[0]))
            LOGGER.info("Obtaining sentiment word list from postgre completed")
        except:
            DB_CONN.rollback()
            logger(sys.exc_info())

    def post_init(self):
        try:
            LOGGER.info('Opening a connection')
            self.connection = SelectConnection(
                parameters=settings.pika_parameters,
                on_open_callback=self.on_connection_open)
            try:
                LOGGER.info('Starting ioloop')
                self.connection.ioloop.start()
            except KeyboardInterrupt:
                # Gracefully close the connection
                self.connection.close()
                # Loop until we're fully closed, will stop on its own
                self.connection.ioloop.start()
        except:
            (etype, eobj, etb) = sys.exc_info()
            print traceback.format_exception(etype, eobj, etb)

    def on_connection_open(self, unused_connection):
        LOGGER.info('Opening a connection completed')
        self.open_channel()

    def open_channel(self):
        LOGGER.info('Opening a channel')
        self.connection.channel(on_open_callback=self.on_channel_open)

    def on_channel_open(self, new_channel):
        LOGGER.info('Opening a channel completed')
        self.channel = new_channel
        self.declare_exchange()

    def declare_exchange(self):
        LOGGER.info('Declaring an exchange')
        self.channel.exchange_declare(
            exchange=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NAME,
            exchange_type=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_TYPE,
            passive=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_PASSIVE,
            durable=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_DURABLE,
            auto_delete=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_AUTO_DELETE,
            internal=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_INTERNAL,
            nowait=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NOWAIT,
            arguments=None,  # Custom key/value pair arguments for the exchange
            callback=self.on_exchange_declared
        )  # Call this method on Exchange.DeclareOk

    def on_exchange_declared(self, unused_frame):
        LOGGER.info('Declaring an exchange completed')
        self.declare_queue()

    def declare_queue(self):
        LOGGER.info('Declaring a queue')
        self.channel.queue_declare(
            callback=self.on_queue_declared,
            queue=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NAME,
            passive=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_PASSIVE,
            durable=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_DURABLE,
            exclusive=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_EXCLUSIVE,
            auto_delete=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_AUTO_DELETE,
            nowait=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NOWAIT,
            arguments=None)

    def on_queue_declared(self, method_frame):
        LOGGER.info('Declaring a queue completed')
        self.bind_queue()

    def bind_queue(self):
        LOGGER.info('Binding a queue')
        self.channel.queue_bind(
            callback=self.on_queue_binded,
            queue=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NAME,
            exchange=settings.RABBITMQ_NEWSFEED_ENTRY_EXCHANGE_NAME,
            routing_key=settings.RABBITMQ_NEWSFEED_ENTRY_ROUTING_KEY)

    def on_queue_binded(self, frame):
        LOGGER.info('Binding a queue completed')
        # Start the thread's activity
        self.start()

    def on_message(self, channel, basic_deliver, properties, body):
        """Invoked by pika when a message is delivered from RabbitMQ. The
        channel is passed for your convenience. The basic_deliver object that
        is passed in carries the exchange, routing key, delivery tag and
        a redelivered flag for the message. The properties passed in is an
        instance of BasicProperties with the message properties and the body
        is the message that was sent.

        :param pika.channel.Channel channel: The channel object
        :param pika.Spec.Basic.Deliver: basic_deliver method
        :param pika.Spec.BasicProperties: properties
        :param str|unicode body: The message body
        """
        LOGGER.info('Received message # %s from %s',
                    basic_deliver.delivery_tag, properties.app_id)
        self.ack_message(basic_deliver.delivery_tag)

        try:
            data = JSON_DECODER.decode(body)
            #pprint(data)
            self.processopinion.process(data)
        except simplejson.JSONDecodeError:
            LOGGER.info(sys.exc_info())

    def ack_message(self, delivery_tag):
        """Acknowledge the message delivery from RabbitMQ by sending a
        Basic.Ack RPC method for the delivery tag.

        :param int delivery_tag: The delivery tag from the Basic.Deliver frame
        """
        LOGGER.info('Acknowledging message %s', delivery_tag)
        self.channel.basic_ack(delivery_tag)

    def run(self):
        LOGGER.info('Start to consume message from queue')
        self.channel.basic_consume(
            consumer_callback=self.on_message,
            queue=settings.RABBITMQ_NEWSFEED_ENTRY_QUEUE_NAME,
            no_ack=
            False,  # Set to True means tell the broker to not expect a response
            exclusive=
            False,  # Set to True means don't allow other consumers on the queue
            consumer_tag=None)  # Specify your own consumer tag
コード例 #11
0
ファイル: amqp.py プロジェクト: engalex/synapse-agent
class Amqp(object):
    def __init__(self, conf):

        # RabbitMQ general options
        self.cacertfile = conf['cacertfile']
        self.certfile = conf['certfile']
        self.exchange = conf['exchange']
        self.status_exchange = conf['status_exchange']
        self.fail_if_no_peer_cert = conf['fail_if_no_peer_cert']
        self.heartbeat = conf['heartbeat']
        self.host = conf['host']
        self.keyfile = conf['keyfile']
        self.password = conf['password']
        self.port = conf['port']
        self.ssl_port = conf['ssl_port']
        self.queue = conf['uuid']
        self.retry_timeout = conf['retry_timeout']
        self.ssl_auth = conf['ssl_auth']
        self.use_ssl = conf['use_ssl']
        self.username = conf['username']
        self.vhost = conf['vhost']

        # Connection and channel initialization
        self.connection = None
        self.channel = None

        # Plain credentials
        credentials = PlainCredentials(self.username, self.password)
        pika_options = {
            'host': self.host,
            'port': self.port,
            'virtual_host': self.vhost,
            'credentials': credentials
        }

        # SSL options
        if self.use_ssl:
            pika_options['ssl'] = True
            pika_options['port'] = self.ssl_port
            if self.ssl_auth:
                pika_options['credentials'] = ExternalCredentials()
                pika_options['ssl_options'] = {
                    'ca_certs': self.cacertfile,
                    'certfile': self.certfile,
                    'keyfile': self.keyfile,
                    'cert_reqs': CERT_REQUIRED
                }

        if self.heartbeat:
            pika_options['heartbeat'] = self.heartbeat

        self.parameters = None

        try:
            self.parameters = pika.ConnectionParameters(**pika_options)
        except TypeError as err:
            self.logger.debug(err)
            # Let's be compatible with original pika version (no integer for
            # heartbeats and no ssl.
            self.logger.warning("Wrong pika lib version, won't use ssl.")
            pika_options['heartbeat'] = True
            if self.use_ssl:
                self.use_ssl = False
                pika_options['port'] = self.port
                del pika_options['ssl']
                if self.ssl_auth:
                    self.ssl_auth = False
                    del pika_options['ssl_options']

            self.parameters = pika.ConnectionParameters(**pika_options)

    def connect(self):
        SelectPoller.TIMEOUT = .1
        self.connection = SelectConnection(self.parameters, self.on_connected)
        self.connection.ioloop.start()

    def close(self, amqperror=False):
        if (self.connection and not self.connection.closing
                and not self.connection.closed):

            self.logger.debug("Closing connection")
            self.connection.close()
            #self.connection.ioloop.start()

    def on_remote_close(self, code, text):
        self.logger.debug("Remote channel close, code %d" % code)
        time.sleep(2)
        if code != 200:
            self.close()
            raise AmqpError(text)

    def on_connection_closed(self, frame):
        self.connection.ioloop.stop()

    def on_connected(self, connection):
        self.connection = connection
        self.connection.add_on_close_callback(self.on_connection_closed)
        self.connection.channel(self.on_channel_open)