Example #1
0
 def __init__(self, hostname, port, vhost, userid, password):
     """connects to broker and provides convenience methods"""
     self.broker = BrokerConnection(hostname=hostname,
                                    port=port,
                                    userid=userid,
                                    password=password,
                                    virtual_host=vhost)
Example #2
0
 def connect(self):
     if not self.connection:
         self.connection = BrokerConnection(hostname=self.config.host,
                                            port=self.config.port,
                                            userid=self.config.user,
                                            password=self.config.password,
                                            virtual_host=self.config.vhost)
Example #3
0
def send_messages(ui, repo, node, **kwargs):

    # Read the config
    get_configuration(ui)

    # Let the user know what is going on
    print "Sending messages to %s" % CONF["BROKER_HOST"]
    print "Please do not interrupt..."

    try:
        # Get the push data
        # TODO: Support pulling from the pushlog db
        pushdata = get_push_data(ui, repo, node)

        # If they don't want AMQP, switch the backend
        if CONF["BROKER_PROTOCOL"] == "STOMP":
            backend = "carrot.backends.pystomp.Backend"
        else:
            backend = None

        # Connect once for all the messages we will send
        connection = BrokerConnection(
            hostname=CONF["BROKER_HOST"],
            port=CONF["BROKER_PORT"],
            userid=CONF["BROKER_USER"],
            password=CONF["BROKER_PASS"],
            backend_cls=backend,
        )

        # Send the overall push message. Most consumers likely
        # only care about this message
        print "    Sending the %s message..." % CONF["LABEL_PUSH"]
        send_push_message(connection, pushdata)

        # Also send messages for each changeset as consumers may be
        # interested in those as well
        print "    Sending individual %s messages..." % CONF["LABEL_CHANGESET"]
        for changedata in pushdata[CONF["LABEL_CHANGESETS"]]:
            changedata["repository"] = pushdata["repository"]
            send_changeset_message(connection, changedata)

        try:
            connection.close()
        except:
            # We don't care about connection close failures
            pass

    except Exception, e:
        # Something went wrong...
        print "ERROR: Hook returned an exception: %s" % e

        if CONF["HG_FAIL_ON_MSG_FAIL"]:
            # Admin wants the hook to fail on the message send failure
            print "Please try pushing again."
            return 1
        else:
            # Admin wants the hook to succeed on the message send failure
            print "Ignoring and continuing the push..."
            return 0
Example #4
0
def send_msg(routing_key, data):
    conn = BrokerConnection(
                hostname=settings.BROKER_HOST,
                port=settings.BROKER_PORT,
                userid=settings.BROKER_USER,
                password=settings.BROKER_PASSWORD,
                virtual_host=settings.BROKER_VHOST)
    publisher = Publisher(connection=conn,
                          exchange="django_send",
                          routing_key=routing_key,
                          exchange_type="topic",
                          )
    publisher.send(data)
    publisher.close()
    conn.close()
Example #5
0
def main():
    logging.basicConfig(level=logging.DEBUG)
    args = parser.parse_args()
    conn = BrokerConnection(
        hostname=args.hostname,
        virtual_host=args.vhost,
        userid=args.user,
        password=args.password,
    )
    publisher = Publisher(auto_declare=False,
                          connection=conn,
                          exchange=args.exchange,
                          routing_key=args.key)
    logging.info("Declaring exchange: %s" % args.exchange)
    publisher.backend.exchange_declare(exchange=args.exchange,
                                       type="topic",
                                       durable=False,
                                       auto_delete=False)
    while True:
        line = sys.stdin.readline()
        if not line:
            break
        logging.debug("Sending message '%s'" % line.strip())
        publisher.send(line.strip())
    publisher.close()
Example #6
0
def establish_connection(hostname=None,
                         userid=None,
                         password=None,
                         virtual_host=None,
                         port=None,
                         ssl=None,
                         insist=None,
                         connect_timeout=None,
                         backend_cls=None,
                         defaults=conf):
    """Establish a connection to the message broker."""
    if insist is None:
        insist = defaults.BROKER_INSIST
    if ssl is None:
        ssl = defaults.BROKER_USE_SSL
    if connect_timeout is None:
        connect_timeout = defaults.BROKER_CONNECTION_TIMEOUT

    return BrokerConnection(hostname or defaults.BROKER_HOST,
                            userid or defaults.BROKER_USER,
                            password or defaults.BROKER_PASSWORD,
                            virtual_host or defaults.BROKER_VHOST,
                            port or defaults.BROKER_PORT,
                            backend_cls=backend_cls or defaults.BROKER_BACKEND,
                            insist=insist,
                            ssl=ssl,
                            connect_timeout=connect_timeout)
Example #7
0
 def setUp(self):
     # single global RPC server thread, ok in test framework
     global test_rpc_service
     if not test_rpc_service:
         test_rpc_service = MockRPCServiceProvider()
     if not self.test_connection:
         self.test_connection = BrokerConnection(**settings.AMQP_CONNECTION)
Example #8
0
    def __init__(self,
                 hostname='localhost',
                 port=5672,
                 userid="collectoruser",
                 password="******",
                 **options):

        conn = BrokerConnection(hostname=hostname,
                                port=port,
                                userid=userid,
                                password=password,
                                virtual_host='collectorvhost')

        try:
            self.publisher = Publisher(connection=conn,
                                       exchange="collector.response",
                                       exchange_type='direct',
                                       routing_key="response",
                                       serializer="json")
        except Exception as ex:
            raise Worker.ConnectionException(ex)

        self.consumer = Consumer(connection=conn,
                                 queue="feed",
                                 exchange_type='topic',
                                 exchange="collector",
                                 routing_key="collector.*.*")
Example #9
0
def cast(msg, event_type, topic, priority):
    yagi.config.setup(config_path='/etc/yagi.conf')
    conf = yagi.config.config_with('rabbit_broker')
    host = conf('host')
    port = conf('port')
    user = conf('user')
    exchange = conf('exchange')
    password = conf('password')
    vhost = conf('vhost')

    message_dict = {
        'message_id': str(uuid.uuid4()),
        'event_type': event_type,
        'publisher_id': 'some_publisher',
        'priority': priority,
        'timestamp': str(datetime.datetime.utcnow()),
        'payload': msg
        }
    conn = BrokerConnection(hostname=host, port=port, userid=user,
             password=password, virtual_host=vhost)
    publisher = Publisher(connection=conn, exchange=exchange,
            routing_key="%s.%s" % (topic, priority), durable=False,
            exchange_type='topic')
    publisher.send(message_dict)
    publisher.close()
 def connect(self):
     if not self.connection:
         self.connection = BrokerConnection(hostname=self.config.host,
                                            port=self.config.port,
                                            userid=self.config.user,
                                            password=self.config.password,
                                            virtual_host=self.config.vhost)
Example #11
0
 def __init__(self, host_name, port, userid, password, virtual_host,
              encoder_class):
     self.q_connection = BrokerConnection(hostname=host_name,
                                          port=port,
                                          userid=userid,
                                          password=password,
                                          virtual_host=virtual_host)
     self.encoder = encoder_class()
Example #12
0
 def add(self):
     broker = BrokerConnection(hostname=self.hostname,
                               port=self.port,
                               userid=self.username,
                               password=self.password,
                               virtual_host=self.vhost)
     with self.lock:
         self._brokers.append(broker)
Example #13
0
 def add_many(self, limit):
     with self.lock:
         for _ in range(0, limit):
             broker = BrokerConnection(hostname=self.hostname,
                                       port=self.port,
                                       userid=self.username,
                                       password=self.password,
                                       virtual_host=self.vhost)
             self._brokers.append(broker)
Example #14
0
 def __init__(self, host_name, port, userid, password, virtual_host,
              encoder_class):
     self.q_connection = BrokerConnection(hostname=host_name,
                                          port=port,
                                          userid=userid,
                                          password=password,
                                          virtual_host=virtual_host)
     self.encoder = encoder_class()
     dispatcher.connect(self.spider_opened, signals.spider_opened)
     dispatcher.connect(self.spider_closed, signals.spider_closed)
    def test_with_statement(self):

        with BrokerConnection(**test_connection_args()) as conn:
            self.assertFalse(conn._closed)
            with Publisher(connection=conn, exchange="F", routing_key="G") \
                    as publisher:
                self.assertFalse(publisher._closed)
        self.assertTrue(conn._closed)
        self.assertTrue(publisher._closed)

        with BrokerConnection(**test_connection_args()) as conn:
            self.assertFalse(conn._closed)
            with Consumer(connection=conn,
                          queue="E",
                          exchange="F",
                          routing_key="G") as consumer:
                self.assertFalse(consumer._closed)
        self.assertTrue(conn._closed)
        self.assertTrue(consumer._closed)
Example #16
0
    def test_messaging(self):
        m = TMessaging(connection=BrokerConnection(backend_cls=PyQueueBackend))
        self.assertTrue(m)

        self.assertEquals(m.fetch(), None)
        mdata = {"name": "Cosmo Kramer"}
        m.send(mdata)
        next_msg = m.fetch()
        next_msg_data = next_msg.decode()
        self.assertEquals(next_msg_data, mdata)
        self.assertEquals(m.fetch(), None)
    def __init__(self, hostname, port, user_id, password, virtual_host, encoder_class):
        self.queue_connection = BrokerConnection(
            hostname=hostname,
            port=port,
            userid=user_id,
            password=password,
            virtual_host=virtual_host
        )

        self.encoder = encoder_class()

        # Setup / Teardown Rabbit plumbing when spider opens / closes
        dispatcher.connect(self.spider_opened, signals.spider_opened)
        dispatcher.connect(self.spider_closed, signals.spider_closed)
Example #18
0
    def establish_consumer_connection(self, consumer):
        # for now all consumers use the same queue connection
        # That may not be the case forever
        config = conf.config_with("rabbit_broker")
        reconnect_delay = int(config("reconnect_delay"))
        max_wait = int(config("max_wait"))

        # This just sets the connection string. It doesn't actually
        # connect to the AMQP server yet.
        connection = BrokerConnection(hostname=config("host"),
                                      port=config("port"),
                                      userid=config("user"),
                                      password=config("password"),
                                      virtual_host=config("vhost"),
                                      ssl=confbool("ssl"))

        auto_delete = consumer.config("auto_delete") == "True" or False
        durable = consumer.config("durable") == "True" or False

        exdurable = confbool(consumer.config("exchange_durable"))
        exauto_delete = confbool(consumer.config("exchange_auto_delete"))

        # try a few times to connect, we might have lost the connection
        retries = 0
        while True:
            try:
                carrot_consumer = NotQuiteSoStupidConsumer(
                    connection=connection,
                    warn_if_exists=True,
                    exchange=consumer.config("exchange"),
                    exchange_type=consumer.config("exchange_type"),
                    routing_key=consumer.config("routing_key"),
                    queue=consumer.queue_name,
                    auto_delete=auto_delete,
                    durable=durable,
                    exchange_durable=exdurable,
                    exchange_auto_delete=exauto_delete,
                )
                consumer.connect(connection, carrot_consumer)
                LOG.info("Connection established for %s" % consumer.queue_name)
                break
            except amqplib.client_0_8.exceptions.AMQPConnectionException, e:
                LOG.error("AMQP protocol error connecting to for queue %s" %
                          consumer.queue_name)
                LOG.exception(e)
            except socket.error, e:
                # lost connection?
                pass
Example #19
0
 def _wait_connection(self,time_to_wait=60):
     """Waits for RabbitMQ connection. """
     _connected = False
     while(not _connected):
         try:
             self.amqp_connection = BrokerConnection(**self.amqp_connection_settings)
             if self.amqp_connection.connection:
                 _connected = True
                 logging.debug('%s connected to AMQP @ %s:%i' % (
                     self.service_name,
                     self.amqp_connection_settings['hostname'],
                     self.amqp_connection_settings['port']))
         except socket_error:
             logging.warn("%s waiting %i sec for RabbitMQ connection..." % (
                 self.service_name, time_to_wait))
             sleep(time_to_wait)
Example #20
0
def get_carrot_connection(config):
    backend = config.get('queue.library', 'pyamqplib')
    log.info("Carrot connnection using %s backend" % backend)
    try:
        port = int(config.get('queue.port', PORT))
    except ValueError:
        port = PORT
    userid = config.get('queue.user_id', USERID)
    password = config.get('queue.password', PASSWORD)
    hostname = config.get('queue.host', HOSTNAME)
    virtual_host = config.get('queue.virtual_host', VIRTUAL_HOST)
    
    backend_cls = 'carrot.backends.%s.Backend' % backend
    return BrokerConnection(hostname=hostname, port=port,
                            userid=userid, password=password,
                            virtual_host=virtual_host,
                            backend_cls=backend_cls)
Example #21
0
    def test_consumer_interface(self):
        to_send = ['No', 'soup', 'for', 'you!']
        messages = []

        def cb(message_data, message):
            messages.append(message_data)

        conn = BrokerConnection(backend_cls='memory')
        consumer = Consumer(connection=conn,
                            queue="test",
                            exchange="test",
                            routing_key="test")
        consumer.register_callback(cb)
        publisher = Publisher(connection=conn,
                              exchange="test",
                              routing_key="test")
        for i in to_send:
            publisher.send(i)
        it = consumer.iterconsume()
        for i in range(len(to_send)):
            it.next()
        self.assertEqual(messages, to_send)
Example #22
0
def main():
    logging.basicConfig(level=logging.INFO)
    args = parser.parse_args()
    conn = BrokerConnection(
        hostname=args.hostname,
        virtual_host=args.vhost,
        userid=args.user,
        password=args.password,
    )
    consumer = Consumer(
        auto_declare=False,
        connection=conn,
        exclusive=True,
        auto_delete=True,
    )
    try:
        logging.info("Creating exchange: %s" % args.exchange)
        consumer.backend.exchange_declare(exchange=args.exchange,
                                          type="topic",
                                          durable=False,
                                          auto_delete=True)
    except Exception, e:
        logging.warning("Failed to create exchange: %s" % e)
Example #23
0
def create_connection():
    return BrokerConnection(backend_cls=StompBackend,
                            **test_stomp_connection_args())
Example #24
0
from carrot.connection import BrokerConnection

from config import BROKER_CONFIG, PRINTER_CONFIG

from pointofsale import printer

if __name__ == '__main__':
    conn = BrokerConnection(**BROKER_CONFIG)

    registry = printer.PrinterRegistry(PRINTER_CONFIG['registry'],
                                       PRINTER_CONFIG['auth_token'])
    p = printer.TestPrinter(PRINTER_CONFIG['name'], registry, conn)
    pm_handler = printer.PrinterMessageThread(p)

    pm_handler.start()
    while True:
        pm_handler.join(1)
        if not pm_handler.is_alive():
            break
Example #25
0
class IMessageBroker(Consumer, Thread):
    """Interface for communicating JSON over AMQP.
    
    Consumer thread interface that can also publish a response for each request with unique id.
    Consumer and publisher use the same AMQP connection.

    Subclass this to implement a worker thread. See the example in the tests.
    """
    # implemented in subclass
    service_name = None
    amqp_connection = None
    amqp_connection_settings = None
    exchange_name = None
    topic = None

    # dynamic instance variables
    binding_key = None
    response_routing_key = None
    req_queue_name = None

    def __init__(self, *args, **kwargs):
        logging.debug("%s starting up" % self.__unicode__())

        # set instance variables
        self.binding_key = '.'.join([self.topic, 'request', '*'])
        self.response_routing_key = '.'.join([self.topic, 'response', '%s'])
        self.req_queue_name = '%s_req' % self.service_name

        # initialize the thread
        Thread.__init__(self, *args, **kwargs)
        # wait for AMQP connection, declare exchange and request queue
        # and bind the consumer
        self._wait_connection()
        self._declare_channel()
        self._init_consumer()

    def __exit__(self, e_type, e_value, e_trace):
        logging.debug('%s exiting' % self.__unicode__())
        if e_type:
            logging.error(e_type(e_value))

    def __unicode__(self):
        return self.service_name

    def _declare_channel(self):
        """Declares exchange and request queue."""
        backend = self.amqp_connection.create_backend()
        backend.exchange_declare(
            exchange=self.exchange_name,
            type="topic",
            durable=True,
            auto_delete=False,)
        backend.queue_declare(
            queue=self.req_queue_name,
            durable=True,
            exclusive=False,
            auto_delete=False,)
        backend.queue_bind(self.req_queue_name,self.exchange_name,self.binding_key)
        logging.debug("%s queue %s bound to %s" % (
            self.exchange_name,
            self.req_queue_name,
            self.binding_key))

    def _wait_connection(self,time_to_wait=60):
        """Waits for RabbitMQ connection. """
        _connected = False
        while(not _connected):
            try:
                self.amqp_connection = BrokerConnection(**self.amqp_connection_settings)
                if self.amqp_connection.connection:
                    _connected = True
                    logging.debug('%s connected to AMQP @ %s:%i' % (
                        self.service_name,
                        self.amqp_connection_settings['hostname'],
                        self.amqp_connection_settings['port']))
            except socket_error:
                logging.warn("%s waiting %i sec for RabbitMQ connection..." % (
                    self.service_name, time_to_wait))
                sleep(time_to_wait)

    def _init_consumer(self):
        Consumer.__init__(self,
            connection=self.amqp_connection,
            exchange=self.exchange_name,
            exchange_type="topic",
            queue=self.req_queue_name,
            )
        # register the callback method
        self.register_callback(self._request_filter) # calls "dispatch"
        self._stop = Event()
        self._stop.set() # set to stopped state

    def _request_filter(self, message_data, message):
        """Filter for incoming AMQP requests.
        
        Expects JSON input as message payload. It has a metadata wrapper with keys
        "q" and "qid", for actual message data and an identifier, respectively.
        Example:
        
        {"qid": 293742, "q": {"hello my friend . we speak over the RPC now . "}}
        """
        logging.debug("consumer received message: \n%s" % message.delivery_info)
        #routing_key = message.delivery_info['routing_key']
        qid = None
        try:
            data = json.loads(message_data)
            qid = data.get('qid')
            request = data.get('q')
            self.dispatch(message, request, qid)
        except:
            logging.error(sys.exc_info()[1])
            return

    def dispatch(self, message, request, qid):
        """AMQP "request" callback handler.

        - message: carrot Message
        - request: JSON data
        - qid: unique request identifier
        
        Do whatever your worker is supposed to do here.
        You can return a response by calling self.return_response(json_response, qid).
        """
        raise NotImplementedError, "Write your own subclass"

    def return_response(self, response, qid):
        """AMQP "response" handler.
        
        Publishes a response message to a temporary queue.
        - response is json, qid is string
        """
        message = json.dumps(response)
        routing_key = self.response_routing_key % qid
        logging.debug("response to %s with routing_key: %s, message: \n%s" % (self.exchange_name, routing_key, message))
        try:
            publisher = Publisher(
                connection=self.amqp_connection,
                exchange=self.exchange_name,
                exchange_type="topic",
                routing_key=routing_key,
                )
            publisher.send(message)
            publisher.close()
        except:
            """Trying to send with broken connection.

            Handle gracefully by waiting for connection and publish again."""
            logging.error('%s AMQP error: %s' % (self.service_name, sys.exc_info()[1]))
            self._wait_connection(5)
            self.return_response(response, qid)

    @property
    def stopped(self):
        return self._stop.isSet()

    def run(self):
        self._stop.clear() # started
        logging.info('%s entering AMQP consumer loop' % self.__unicode__())
        it = self.iterconsume()
        while not self.stopped:
            try:
                it.next()
            except KeyboardInterrupt:
                logging.warn("KB interrupt")
            except (AMQPConnectionException, IOError, AttributeError):
                """AMQPConnectionException or IOError if the AMQ socket closes.
                AttributeError if channel has been closed.

                Handle gracefully by waiting for connection and re-enter consumer loop,
                unless the service stop flag is set.
                """
                if self.stopped:
                    break

                # else reconnect
                logging.error('%s AMQP error: %s' % (self.service_name, sys.exc_info()[1]))
                self._wait_connection()
                self._init_consumer()
                self._stop.clear() # continue in started mode
                it = self.iterconsume()
                continue
            except StopIteration:
                """Happens at cancel() and on lost connection, 
                if IOError exception handler could not restore consumption loop."""
                logging.debug('%s %s' % (self.__unicode__(), sys.exc_info()[1]))
                logging.info('%s break out of consumer loop' % self.__unicode__())
                self._stop.set()
                break
            except:
                logging.error("BUG")
                logging.error('%s %s' % (self.__unicode__(), sys.exc_info()[1]))
                traceback.print_tb(sys.exc_info()[2],10)

        try:
            self.amqp_connection.close()
        except:
            logging.debug('%s %s' % (self.__unicode__(), sys.exc_info()[1]))

        logging.info('%s thread exiting' % self.__unicode__())
        exit()

    def stop(self,*args):
        """Stop consumer"""
        logging.debug('%s stop' % self.__unicode__())
        try:
            try:
                # set the Event
                self._stop.set()
                # release the consumer from iterconsume
                self.cancel()
            except:
                pass
                #logging.debug('%s %s' % (self.__unicode__(), sys.exc_info()[1]))
        finally:
            try:
                self.amqp_connection.close()
            except IOError:
                logging.debug(sys.exc_info()[1])
            if self.amqp_connection.pool:
                self.amqp_connection.release()
Example #26
0
class GenericPublisher(object):
    def __init__(self, config, exchange=None, connect=True):
        self.config = config
        self.exchange = exchange
        self.connection = None
        if connect:
            self.connect()

    # Connect to the message broker
    def connect(self):
        if not self.connection:
            self.connection = BrokerConnection(hostname=self.config.host,
                                               port=self.config.port,
                                               userid=self.config.user,
                                               password=self.config.password,
                                               virtual_host=self.config.vhost)

    # Disconnect from the message broker
    def disconnect(self):
        if self.connection:
            self.connection.close()
            self.connection = None

    # Used to publish a pulse message to the proper exchange
    def publish(self, message):

        # Make suere there is an exchange given
        if not self.exchange:
            raise InvalidExchange(self.exchange)

        # Make sure there is a message given
        if not message:
            raise MalformedMessage(message)

        # Have the message prepare and validate itself
        message._prepare()

        # Connect to the broker if we haven't already
        if not self.connection:
            self.connect()

        # Set up our broker publisher
        self.publisher = Publisher(connection=self.connection,
                                   exchange=self.exchange,
                                   exchange_type="topic",
                                   routing_key=message.routing_key)

        # The message is actually a simple envelope format with a payload and
        # some metadata
        final_data = {}
        final_data['payload'] = message.data
        final_data['_meta'] = message.metadata.copy()
        final_data['_meta'].update({
            'exchange':
            self.exchange,
            'routing_key':
            message.routing_key,
            'serializer':
            self.config.serializer,
            'sent':
            time_to_string(datetime.now(timezone(self.config.broker_timezone)))
        })

        # Send the message
        self.publisher.send(final_data, serializer=self.config.serializer)

        # Close the publishing connection
        self.publisher.close()
from carrot.connection import BrokerConnection
from carrot.messaging import Consumer

if __name__ == '__main__':
    connection = BrokerConnection(hostname='localhost',
                                  port=5672,
                                  userid='guest',
                                  password='******',
                                  virtual_host=None)
    consumer = Consumer(connection=connection,
                        queue="transactions",
                        exchange="transactions")

    def print_message(message_data, message):
        print(message_data)
        message.ack()

    consumer.register_callback(print_message)
    consumer.wait()
class GenericConsumer(object):

    def __init__(self, config, exchange=None, connect=True, heartbeat=False,
                 **kwargs):
        self.config     = config
        self.exchange   = exchange
        self.connection = None
        self.durable    = False
        self.applabel   = ''
        self.heartbeat  = heartbeat
        for x in ['applabel','topic','callback','durable']:
            if x in kwargs:
                setattr(self, x, kwargs[x])
                del kwargs[x]

        if connect:
            self.connect()

    # Sets vairables
    def configure(self, **kwargs):
        for x in kwargs:
            setattr(self, x, kwargs[x])

    # Connect to the message broker
    def connect(self):
        if not self.connection:
            self.connection = BrokerConnection(hostname=self.config.host,
                                               port=self.config.port,
                                               userid=self.config.user,
                                               password=self.config.password,
                                               virtual_host=self.config.vhost)

    # Disconnect from the message broker
    def disconnect(self):
        if self.connection:
            self.connection.close()

    # Support purging messages that are already in the queue on the broker
    # TODO: I think this is only supported by the amqp backend
    def purge_existing_messages(self):

        # Make sure there is an applabel given
        if self.durable and not self.applabel:
            raise InvalidAppLabel('Durable consumers must have an applabel')
        
        # Purge the queue of existing messages
        self.connection.create_backend().queue_purge(self.applabel)

    # Blocks and calls the callback when a message comes into the queue
    # For info on one script listening to multiple channels, see
    # http://ask.github.com/carrot/changelog.html#id1
    def listen(self, callback=None):

        # One can optionally provide a callback to listen (if it wasn't already)
        if callback:
            self.callback = callback

        # Make suere there is an exchange given
        if not self.exchange:
            raise InvalidExchange(self.exchange)

        # Make sure there is a topic given
        if not self.topic:
            raise InvalidTopic(self.topic)

        # Make sure there is an applabel given
        if self.durable and not self.applabel:
            raise InvalidAppLabel('Durable consumers must have an applabel')

        # Make sure there is a callback given
        if not self.callback or not hasattr(self.callback, '__call__'):
            raise InvalidCallback(self.callback)

        # Connect to the broker if we haven't already
        if not self.connection:
            self.connect()

        # Set up our broker consumer
        self.consumer = Consumer(connection=self.connection,
                                   queue=self.applabel,
                                   exchange=self.exchange,
                                   exchange_type="topic",
                                   auto_declare=False,
                                   routing_key=self.topic)

        # We need to manually create / declare the queue
        self.consumer.backend.queue_declare(queue=self.applabel,
                                            durable=self.durable,
                                            exclusive=False,
                                            auto_delete=not self.durable,
                                            arguments=self.consumer.queue_arguments,
                                            warn_if_exists=False)

        # No need to manually create the exchange, as the producer creates it
        # and we expect it to just be there

        # We support multiple bindings if we were given an array for the topic
        if not isinstance(self.topic, list):
            self.topic = [self.topic]

        # We need to bind the queue to the exchange with the specified keys
        if self.consumer.queue:
            for routing_key in self.topic:
                self.consumer.backend.queue_bind(queue=self.consumer.queue,
                                                 exchange=self.exchange,
                                                 routing_key=routing_key)
            if self.heartbeat:
                self.consumer.backend.queue_bind(queue=self.consumer.queue,
                                                 exchange='org.mozilla.exchange.pulse.test',
                                                 routing_key='heartbeat')

        # Register the callback the user wants
        self.consumer.register_callback(self.callback)

        # This blocks, and then calls the user callback every time a message 
        # comes in
        self.consumer.wait()

        # Likely never get here but can't hurt
        self.disconnect()
Example #29
0
def create_backend():
    return PyQueueBackend(connection=BrokerConnection())
Example #30
0
 def __init__(self, hostname, port, vhost, userid, password):
     """connects to broker and provides convenience methods"""
     self.broker = BrokerConnection(hostname=hostname, port=port,
                                    userid=userid, password=password,
                                    virtual_host=vhost)
Example #31
0
class Connection:
    def __init__(self, hostname, port, vhost, userid, password):
        """connects to broker and provides convenience methods"""
        self.broker = BrokerConnection(hostname=hostname, port=port,
                                       userid=userid, password=password,
                                       virtual_host=vhost)
    
    def __del__(self):
        self.broker.close()

    def declare(self, exchange, exchange_type, binding="", queue=""):
        """declares the exchange, the queue and binds the queue to the exchange
        
        exchange        - exchange name
        exchange_type   - direct, topic, fanout
        binding         - binding to queue (optional)
        queue           - queue to bind to exchange using binding (optional)
        """
        if (binding and not queue) or (queue and not binding):
            if queue and not exchange_type == "fanout":
                raise Error("binding and queue are not mutually exclusive")

        consumer = Consumer(connection=self.broker,
                            exchange=exchange, exchange_type=exchange_type,
                            routing_key=binding, queue=queue)
        consumer.declare()
        consumer.close()

    def consume(self, queue, limit=None, callback=None, auto_declare=False):
        """consume messages in queue
        
        queue           - name of queue
        limit           - amount of messages to iterate through (default: no limit)

        callback        - method to call when a new message is received
                          must take two arguments: message_data, message
                          must send the acknowledgement: message.ack()
                          default: print message to stdout and send ack

        auto_declare    - automatically declare the queue (default: false)
        """
        if not callback:
            callback = _consume_callback

        consumer = Consumer(connection=self.broker, queue=queue,
                            auto_declare=auto_declare)

        consumer.register_callback(callback)
        for message in consumer.iterqueue(limit=limit, infinite=False):
            consumer.receive(message.payload, message)

        consumer.close()

    def publish(self, exchange, routing_key, message,
                auto_declare=False, persistent=True):
        """publish a message to exchange using routing_key
        
        exchange        - name of exchange
        routing_key     - interpretation of routing key depends on exchange type
        message         - message content to send
        auto_declare    - automatically declare the exchange (default: false)
        persistent      - store message on disk as well as memory (default: True)
        """
        delivery_mode = 2
        if not persistent:
            delivery_mode = 1

        publisher = Publisher(connection=self.broker,
                              exchange=exchange, routing_key=routing_key,
                              auto_declare=auto_declare)

        publisher.send(message, delivery_mode=delivery_mode)
        publisher.close()
Example #32
0
class Connection:
    def __init__(self, hostname, port, vhost, userid, password):
        """connects to broker and provides convenience methods"""
        self.broker = BrokerConnection(hostname=hostname,
                                       port=port,
                                       userid=userid,
                                       password=password,
                                       virtual_host=vhost)

    def __del__(self):
        self.broker.close()

    def declare(self, exchange, exchange_type, binding="", queue=""):
        """declares the exchange, the queue and binds the queue to the exchange
        
        exchange        - exchange name
        exchange_type   - direct, topic, fanout
        binding         - binding to queue (optional)
        queue           - queue to bind to exchange using binding (optional)
        """
        if (binding and not queue) or (queue and not binding):
            if queue and not exchange_type == "fanout":
                raise Error("binding and queue are not mutually exclusive")

        consumer = Consumer(connection=self.broker,
                            exchange=exchange,
                            exchange_type=exchange_type,
                            routing_key=binding,
                            queue=queue)
        consumer.declare()
        consumer.close()

    def consume(self, queue, limit=None, callback=None, auto_declare=False):
        """consume messages in queue
        
        queue           - name of queue
        limit           - amount of messages to iterate through (default: no limit)

        callback        - method to call when a new message is received
                          must take two arguments: message_data, message
                          must send the acknowledgement: message.ack()
                          default: print message to stdout and send ack

        auto_declare    - automatically declare the queue (default: false)
        """
        if not callback:
            callback = _consume_callback

        consumer = Consumer(connection=self.broker,
                            queue=queue,
                            auto_declare=auto_declare)

        consumer.register_callback(callback)
        for message in consumer.iterqueue(limit=limit, infinite=False):
            consumer.receive(message.payload, message)

        consumer.close()

    def publish(self,
                exchange,
                routing_key,
                message,
                auto_declare=False,
                persistent=True):
        """publish a message to exchange using routing_key
        
        exchange        - name of exchange
        routing_key     - interpretation of routing key depends on exchange type
        message         - message content to send
        auto_declare    - automatically declare the exchange (default: false)
        persistent      - store message on disk as well as memory (default: True)
        """
        delivery_mode = 2
        if not persistent:
            delivery_mode = 1

        publisher = Publisher(connection=self.broker,
                              exchange=exchange,
                              routing_key=routing_key,
                              auto_declare=auto_declare)

        publisher.send(message, delivery_mode=delivery_mode)
        publisher.close()
Example #33
0
def establish_test_connection():
    return BrokerConnection(**test_connection_args())
Example #34
0
"""Message-classes."""
import os, subprocess
from os.path import join, split, splitext, exists
from carrot.connection import BrokerConnection

conn = BrokerConnection(hostname="localhost", port=5672,
                        userid="test", password="******",
                        virtual_host="test")

arrot.messaging import Consumer
consumer = Consumer(connection=conn, queue="feed",
                    exchange="feed", routing_key="importer")

def import_feed_callback(message_data, message):
    feed_url = message_data["import_feed"]
    print("Got feed import message for: %s" % feed_url)
    # something importing this feed url
    # import_feed(feed_url)
    message.ack()

consumer.register_callback(import_feed_callback)
consumer.wait() # Go into the consumer loop.
Example #35
0
class GenericConsumer(object):
    def __init__(self,
                 config,
                 exchange=None,
                 connect=True,
                 heartbeat=False,
                 **kwargs):
        self.config = config
        self.exchange = exchange
        self.connection = None
        self.durable = False
        self.applabel = ''
        self.heartbeat = heartbeat
        for x in ['applabel', 'topic', 'callback', 'durable']:
            if x in kwargs:
                setattr(self, x, kwargs[x])
                del kwargs[x]

        if connect:
            self.connect()

    # Sets vairables
    def configure(self, **kwargs):
        for x in kwargs:
            setattr(self, x, kwargs[x])

    # Connect to the message broker
    def connect(self):
        if not self.connection:
            self.connection = BrokerConnection(hostname=self.config.host,
                                               port=self.config.port,
                                               userid=self.config.user,
                                               password=self.config.password,
                                               virtual_host=self.config.vhost)

    # Disconnect from the message broker
    def disconnect(self):
        if self.connection:
            self.connection.close()

    # Support purging messages that are already in the queue on the broker
    # TODO: I think this is only supported by the amqp backend
    def purge_existing_messages(self):

        # Make sure there is an applabel given
        if self.durable and not self.applabel:
            raise InvalidAppLabel('Durable consumers must have an applabel')

        # Purge the queue of existing messages
        self.connection.create_backend().queue_purge(self.applabel)

    # Blocks and calls the callback when a message comes into the queue
    # For info on one script listening to multiple channels, see
    # http://ask.github.com/carrot/changelog.html#id1
    def listen(self, callback=None):

        # One can optionally provide a callback to listen (if it wasn't already)
        if callback:
            self.callback = callback

        # Make suere there is an exchange given
        if not self.exchange:
            raise InvalidExchange(self.exchange)

        # Make sure there is a topic given
        if not self.topic:
            raise InvalidTopic(self.topic)

        # Make sure there is an applabel given
        if self.durable and not self.applabel:
            raise InvalidAppLabel('Durable consumers must have an applabel')

        # Make sure there is a callback given
        if not self.callback or not hasattr(self.callback, '__call__'):
            raise InvalidCallback(self.callback)

        # Connect to the broker if we haven't already
        if not self.connection:
            self.connect()

        # Set up our broker consumer
        self.consumer = Consumer(connection=self.connection,
                                 queue=self.applabel,
                                 exchange=self.exchange,
                                 exchange_type="topic",
                                 auto_declare=False,
                                 routing_key=self.topic)

        # We need to manually create / declare the queue
        self.consumer.backend.queue_declare(
            queue=self.applabel,
            durable=self.durable,
            exclusive=False,
            auto_delete=not self.durable,
            arguments=self.consumer.queue_arguments,
            warn_if_exists=False)

        # No need to manually create the exchange, as the producer creates it
        # and we expect it to just be there

        # We support multiple bindings if we were given an array for the topic
        if not isinstance(self.topic, list):
            self.topic = [self.topic]

        # We need to bind the queue to the exchange with the specified keys
        if self.consumer.queue:
            for routing_key in self.topic:
                self.consumer.backend.queue_bind(queue=self.consumer.queue,
                                                 exchange=self.exchange,
                                                 routing_key=routing_key)
            if self.heartbeat:
                self.consumer.backend.queue_bind(
                    queue=self.consumer.queue,
                    exchange='org.mozilla.exchange.pulse.test',
                    routing_key='heartbeat')

        # Register the callback the user wants
        self.consumer.register_callback(self.callback)

        # This blocks, and then calls the user callback every time a message
        # comes in
        self.consumer.wait()

        # Likely never get here but can't hurt
        self.disconnect()
import jsonrpclib
from carrot.connection import BrokerConnection
from carrot.messaging import Consumer

conn = BrokerConnection(hostname="localhost", port=5672, userid="guest", password="******", virtual_host="/")

consumer = Consumer(connection=conn, queue="po_box", exchange="sorting_room", routing_key="jason")


def amqp_callback(message_data, message):
    server = jsonrpclib.Server("http://localhost:8080")
    server.ping(message_data)
    print jsonrpclib.history.response
    message.ack()


consumer.register_callback(amqp_callback)
consumer.wait()  # Go into the consumer loop.
conn.close()
class GenericPublisher(object):

    def __init__(self, config, exchange=None, connect=True):
        self.config = config
        self.exchange = exchange
        self.connection = None
        if connect:
            self.connect()

    # Connect to the message broker
    def connect(self):
        if not self.connection:
            self.connection = BrokerConnection(hostname=self.config.host,
                                               port=self.config.port,
                                               userid=self.config.user,
                                               password=self.config.password,
                                               virtual_host=self.config.vhost)

    # Disconnect from the message broker
    def disconnect(self):
        if self.connection:
            self.connection.close()
            self.connection = None

    # Used to publish a pulse message to the proper exchange
    def publish(self, message):

        # Make suere there is an exchange given
        if not self.exchange:
            raise InvalidExchange(self.exchange)

        # Make sure there is a message given
        if not message:
            raise MalformedMessage(message)

        # Have the message prepare and validate itself
        message._prepare()

        # Connect to the broker if we haven't already
        if not self.connection:
            self.connect()

        # Set up our broker publisher
        self.publisher = Publisher(connection=self.connection,
                                   exchange=self.exchange,
                                   exchange_type="topic",
                                   routing_key=message.routing_key)

        # The message is actually a simple envelope format with a payload and
        # some metadata
        final_data = {}
        final_data['payload'] = message.data
        final_data['_meta'] = message.metadata.copy()
        final_data['_meta'].update({
            'exchange': self.exchange,
            'routing_key': message.routing_key,
            'serializer': self.config.serializer,
            'sent': time_to_string(datetime.now(timezone(self.config.broker_timezone)))
        })

        # Send the message
        self.publisher.send(final_data, serializer=self.config.serializer)

        # Close the publishing connection
        self.publisher.close()
Example #38
0
class AmqpbusTests(unittest.TestCase):
    """Tests the AMQP communication.
    """
    test_connection = None

    def setUp(self):
        # single global RPC server thread, ok in test framework
        global test_rpc_service
        if not test_rpc_service:
            test_rpc_service = MockRPCServiceProvider()
        if not self.test_connection:
            self.test_connection = BrokerConnection(**settings.AMQP_CONNECTION)

    def tearDown(self):
        test_rpc_service.stop()
        self.test_connection.close()

    def test_consumer(self):
        """AMQP->RPC->AMQP
        
        Send a AMQP message, and test RPCConsumer response.
        Uses a mock RPC server that the consumer will call.
        Check the consumer AMQP response with test consumer.
        """
        class TestConsumer(IMessageBroker):
            service_name = 'TestConsumer'
            exchange_name = 'Test'
            topic = 'test'
            amqp_connection_settings = settings.AMQP_CONNECTION

            def dispatch(self, message, request, qid):
                """ AMQP -> RPC dispatcher.
                """
                logging.info('dispatching AMQP -> RPC')
                response = {}
                if qid:
                    # call remote RPC
                    # this message has an qid so it expects a response
                    response['msg'] = test_rpc_service.push(request)
                    message.ack()
                    # return the response to AMQP, the caller should be listening ..
                    self.return_response(response,qid)
                else:
                    # no qid, so do something stateless .. 
                    print request
                    message.ack()

        try:
            consumer = TestConsumer()
            self.assertEquals('test.request.*',consumer.binding_key)
            self.assertEquals('test.response.%s',consumer.response_routing_key)

            consumer.start()
            test_rpc_service.start()
            test_rpc_service.messages = []
            # allow consumer to start
            sleep(0.2)
            self.assert_(not consumer.stopped)
            self.assert_(consumer.isAlive())

            # test variables
            qid = str(randrange(0,999999))
            jsondata = {'msg':'hello rpc'}

            _publisher = Publisher(
                connection=self.test_connection,
                exchange='Test',
                exchange_type="topic",
                routing_key='test.request.'+qid,
                )

            # test channel
            backend = self.test_connection.create_backend()
            backend.queue_declare(
                queue="test",
                durable=False,
                exclusive=False,
                auto_delete=True,)
            backend.queue_bind("test",'Test','test.response.'+qid)
            _consumer = Consumer(
                connection=self.test_connection,
                exchange='Test',
                exchange_type="topic",
                queue="test",
                )
            _consumer.discard_all()

            logging.debug('publishing JSON message to RPC')
            data_on_the_wire = json.dumps({'q': jsondata, 'qid': qid})
            _publisher.send(data_on_the_wire)

            # allow data to pass the wire
            sleep(0.2)

            # retrieve dispatcher response
            response = _consumer.fetch()
            self.assert_(response, 'No response')
            data = json.loads(response.payload)
            self.assert_(len(data['msg']) > 0) # assert non-empty response
            self.assertEquals('ok',data['msg'])

            # check dispatcher RPC function
            self.assert_(len(test_rpc_service.messages) > 0, 'Message did not arrive')
            self.assertEquals(test_rpc_service.messages[0], jsondata)
        finally:
            try:
                consumer.stop()
            except:
                pass
            try:
                _consumer.close()
            except:
                pass
            test_rpc_service.stop()
            self.assert_(consumer.stopped)