Example #1
0
    def __init__(self, userid, pubsub, **routing):
        self._userid = userid
        
        #websocket connection
        self._closing = False
        self._pubsub = pubsub
        self._pikaclient = None
        self._channel = None
        self._consumers = []
        self._fsm = Subfsm(self)
        self._tmpbound = False
        self._bound = False

        self._exchange       = routing.get("exchange", None)
        self._exchangetype   = routing.get("exchange_type", None)
        self._expire         = routing.get("expire", None)
        self._queuename      = routing.get("queuename", None)
        self._routings       = routing.get("routings", [])
        self._tmp_queuename  = routing.get("tmp_queuename", None)
        self._tmp_routings   = routing.get("tmp_routings", [])

        if not self._tmp_queuename:
            self._tmpbound = True
        if not self._queuename:
            self._bound = True
Example #2
0
class PikaConsumer(object):

    def __init__(self, userid, pubsub, **routing):
        self._userid = userid
        
        #websocket connection
        self._closing = False
        self._pubsub = pubsub
        self._pikaclient = None
        self._channel = None
        self._consumers = []
        self._fsm = Subfsm(self)
        self._tmpbound = False
        self._bound = False

        self._exchange       = routing.get("exchange", None)
        self._exchangetype   = routing.get("exchange_type", None)
        self._expire         = routing.get("expire", None)
        self._queuename      = routing.get("queuename", None)
        self._routings       = routing.get("routings", [])
        self._tmp_queuename  = routing.get("tmp_queuename", None)
        self._tmp_routings   = routing.get("tmp_routings", [])

        if not self._tmp_queuename:
            self._tmpbound = True
        if not self._queuename:
            self._bound = True

    def start(self):
        _logger.debug("start consumer %s " % self._userid)

        if not self._exchange or not self._exchangetype:
            _logger.error("exchange name or exchange type missed")
            return
        
        _logger.info("fire Subfsm.SUB_EVENT_START")
        self._fsm.fire_event(Subfsm.SUB_EVENT_START)

    def execstart(self):
        # get one rabbitmq connection
        self._pikaclient = SubConnectionMgr.connection()
        if self._pikaclient:
            self._pikaclient.addconsumer(self)

        #create the channel if the connection is opened
        if self._pikaclient.isconnected():
            self.connect()
        else:
            _logger.debug("pika is not connected")
            
        
    def connect(self):
        _logger.debug("begin connect channel %s" % self._userid)

        #clear all the consumers before connect
        del self._consumers[:]

        self._pikaclient._connection.channel(self.__on_channel_open)

    def __on_channel_closed(self, channel, reply_code, reply_text):
        _logger.error("Channel %i was closed: (%s) %s" % (channel, reply_code, reply_text))
        _logger.info("fire Subfsm.SUB_EVENT_DISCONNECTED")
        self._fsm.fire_event(Subfsm.SUB_EVENT_DISCONNECTED)

    def __clear_existconsumers(self):
        if len(self._channel.consumer_tags) == 0:
            _logger.info("there is no consumers on the channel")
            return

        _logger.info("find other consumers")

    def __on_channel_open(self, channel):
        _logger.debug("__on_channel_open %s" % self._userid)
        self._channel = channel
        self.__clear_existconsumers()
        self._channel.add_on_close_callback(self.__on_channel_closed)
        self._channel.add_on_cancel_callback(self.__on_consumer_cancelled)
        try:
            self._channel.exchange_declare(exchange = self._exchange,
                                          exchange_type = self._exchangetype,
                                          auto_delete = False,
                                          durable = False,
                                          callback = self.__on_exchange_declared)
        except Exception as e:
            _logger.error("exchange_declare error {0}".format(e))

    def __on_exchange_declared(self, frame):
        _logger.debug("begin __on_exchange_declared %s" % self._userid)
        try:
            #declare queue
            if self._queuename:
                self._channel.queue_declare(auto_delete = False,
                                            queue = self._queuename,
                                            durable = False,
                                            exclusive = False,
                                            callback = self.__on_queue_declared)
            #declare temp queue
            if self._tmp_queuename:
                self._channel.queue_declare(auto_delete = True,
                                            queue = self._tmp_queuename,
                                            durable = False,
                                            exclusive = True,
                                            callback = self.__on_tmp_queue_declared)
        except Exception as e:
            _logger.error("queue_declare error {0}".format(e))

    def __on_queue_declared(self, frame):
        _logger.debug("begin __on_queue_declared %s" % self._userid)
        lastbound = False
        for item in self._routings:
            if item == self._routings[-1]:
                lastbound = True

            try:
                _logger.info("bind %s" % item)
                self._channel.queue_bind(exchange = self._exchange,
                                         queue = self._queuename,
                                         routing_key = item,
                                         callback = lambda frame, lastbound = lastbound:self.__on_queue_bound(frame, lastbound))
            except Exception as e:
                _logger.error("queue_bind error {0}".format(e))

    def __on_queue_bound(self, frame, lastbound):
        _logger.debug("begin __on_queue_bound %s" % self._userid)

        try:
            consumer = self._channel.basic_consume(consumer_callback = self.__on_pika_message,
                                                   queue = self._queuename,
                                                   no_ack = False)
            self._consumers.append(consumer)
            self._pubsub.connected()
        except Exception as e:
            _logger.error("cosume error {0}".format(e))

        if lastbound:
            self._bound = True
            self.__check_connected()

    def __on_tmp_queue_declared(self, frame):
        _logger.debug("begin __on_tmp_queue_declared %s" % self._userid)
        lastbound = False
        for item in self._tmp_routings:
            if item == self._tmp_routings[-1]:
                lastbound = True

            try:
                _logger.info("bind %s" % item)
                self._channel.queue_bind(exchange = self._exchange,
                                        queue = self._tmp_queuename,
                                        routing_key = item,
                                        callback = lambda frame, lastbound = lastbound: self.__on_tmp_queue_bound(frame, lastbound))
            except Exception as e:
                _logger.error("queue_bind error {0}".format(e))

    def __on_tmp_queue_bound(self, frame, lastbound):
        _logger.debug("begin __on_tmp_queue_bound %s" % self._userid)

        try:
            consumer = self._channel.basic_consume(consumer_callback = self.__on_tmp_pika_message,
                                                   queue = self._tmp_queuename,
                                                   no_ack = True)
            self._consumers.append(consumer)
            self._pubsub.connected()
        except Exception as e:
            _logger.error("cosume error {0}".format(e))

        if lastbound:
            self._tmpbound = True
            self.__check_connected()

    def __check_connected(self):
        _logger.info("check connected bound = %s and tmpbound = %s" % (self._bound, self._tmpbound))
        if self._bound and self._tmpbound:
            _logger.info("fire Subfsm.SUB_EVENT_CONNECTED")
            self._fsm.fire_event(Subfsm.SUB_EVENT_CONNECTED)

    def __on_pika_message(self, channel, method, header, body):
        _logger.debug("begin __on_pika_message %s %r" % (self._userid, body))
        if self._pubsub:
            self._pubsub.add_msg(body)
            self._channel.basic_ack(method.delivery_tag)
        else:
            _logger.error("connection aready closed")
            self.execstop()
            
    def __on_tmp_pika_message(self, channel, method, header, body):
        _logger.debug("begin __on_tmp_pika_message %s %r" % (self._userid, body))
        if self._pubsub:
            self._pubsub.add_tmpmsg(body)        
        else:
            _logger.error("connection aready closed")
            self.execstop()

    def __on_consumer_cancelled(self, method_frame):
        _logger.info("consumer cancelled %s" % self._userid)
        #close normal do nothing
        if self._closing:
            return

        #cancelled by the pika, we will close the channel
        if self._channel:
           self._channel.close()

    def close(self):
        #close normal when user offline
        self._pubsub = None
        _logger.info("fire Subfsm.SUB_EVENT_STOP")
        self._fsm.fire_event(Subfsm.SUB_EVENT_STOP)

    def execstop(self):
        self._pubsub = None
        self._closing = True

        #cancel all the consumers
        for item in self._consumers:
            self._channel.basic_cancel(callback = self.__on_consumer_cancelled, consumer_tag = item)

        del self._consumers[:]

        #close channel
        if self._channel:
            self._channel.close()

    def isclosed(self):
        return self._closing