Exemple #1
0
    def __init__(self, config):
        """Init the Pika AMQP 0.9.1 wrapper client.

        :type config: BaseAMQPClientConfig
        :param config: The configuration for the AMQP client.
        """
        # Define potential credentials
        if config.username:
            from Cerebrum.Utils import read_password
            cred = pika.credentials.PlainCredentials(
                config.username,
                read_password(config.username,
                              config.hostname))
            ssl_opts = None
        else:
            raise ClientErrors.ConfigurationFormatError(
                "Configuration contains neither 'username' or 'cert' value")
        # Create connection-object
        try:
            self.conn_params = pika.ConnectionParameters(
                host=config.hostname,
                port=config.port,
                virtual_host=config.virtual_host,
                credentials=cred,
                ssl=config.tls_on,
                ssl_options=ssl_opts)
        except Exception as e:
            raise ClientErrors.ConnectionError(
                'Invalid connection parameters: {}'.format(e))
        self.channel = self.connection = None
Exemple #2
0
    def publish(self, messages, durable=True):
        """Publish a message to the exchange.

        :type messages: dict or list of dicts.
        :param messages: The message(s) to publish.

        :type durable: bool
        :param durable: If this message should be durable.
        """
        if isinstance(messages, (dict, scim.Event)):
            messages = [messages]
        elif not isinstance(messages, list):
            raise TypeError('messages must be a dict, event or a list thereof')
        for message in messages:
            if not isinstance(message, (dict, scim.Event)):
                raise TypeError('messages must be a dict, '
                                'Event or a list thereof')
            try:
                err_msg = 'Could not generate routing key'
                if isinstance(message, dict):
                    if 'routing-key' in message:
                        event_type = message['routing-key']
                    else:
                        event_type = 'unknown'
                    payload = message
                else:
                    event_type = message.key
                    payload = message.get_payload()
                msg_body = dict(
                    filter(lambda x: x[0] != 'routing-key', payload.items()))
                err_msg = ('Could not generate'
                           ' application/json content from message')
                msg_body = json.dumps(msg_body)
            except Exception as e:
                raise ClientErrors.MessageFormatError('{0}: {1}'.format(
                    err_msg, e))
            try:
                if self.channel.basic_publish(
                        exchange=self.exchange,
                        routing_key=event_type,
                        body=msg_body,
                        properties=pika.BasicProperties(
                            # Delivery mode:
                            # 1: Non-persistent
                            # 2: Persistent
                            delivery_mode=2,
                            content_type='application/json'),
                        # Makes publish return false if
                        # the message is not routed / published
                        mandatory=False,
                        # TODO: Should we enable immediate?
                ):
                    return True
                else:
                    raise Exception('Broker did not confirm message delivery')
            except Exception as e:
                raise ClientErrors.MessagePublishingError(
                    'Unable to publish message: {0!r}'.format(e))
Exemple #3
0
 def open(self):
     """Open connection"""
     try:
         self.connection = pika.BlockingConnection(self.conn_params)
     except Exception as e:
         raise ClientErrors.ConnectionError(
             'Unable to connect to broker: {}'.format(e))
     # Set up channel
     self.channel = self.connection.channel()
    def publish(self, routing_key, message, durable=True):
        """Publish a message to the exchange.

        :type messages: dict or list of dicts.
        :param messages: The message(s) to publish.

        :type durable: bool
        :param durable: If this message should be durable.
        """
        try:
            routing_key = routing_key or 'unknown'

            if isinstance(message, basestring):
                # Validate any previously stored json strings?
                # message = json.loads(message)
                msg_body = six.text_type(message)
            else:
                msg_body = json.dumps(message)
        except Exception as e:
            raise ClientErrors.MessageFormatError(
                'Unable to format message: {0!r}'.format(e))
        try:
            if self.channel.basic_publish(
                    exchange=self.exchange_name,
                    routing_key=routing_key,
                    body=msg_body,
                    properties=pika.BasicProperties(
                        delivery_mode=DELIVERY_PERSISTENT,
                        content_type=CONTENT_TYPE),
                    # Makes publish return false if
                    # the message is not routed / published
                    mandatory=False):
                return True
            else:
                raise Exception('Broker did not confirm message delivery')
        except Exception as e:
            raise ClientErrors.MessagePublishingError(
                'Unable to publish message: {0!r}'.format(e))
Exemple #5
0
    def publish(self, messages, durable=True):
        """
        Publish a message to the exchange after scheduling it
        in case it is marked for scheduling

        :type messages: dict, scim.Event or list of dicts and / or scim.Event
        :param messages: The message(s) to publish

        :type durable: bool
        :param durable: If this message should be durable

        :rtype: dict
        :return: A dict of jti:(celery.result.AsyncResult, eta)
        """
        from Cerebrum.modules.celery_tasks.apps.scheduler import schedule_message
        super(SchedulingAndPublishingAMQP091Client,
              self).publish(messages, durable)
        if isinstance(messages, (dict, scim.Event)):
            messages = [messages]
        elif not isinstance(messages, list):
            raise TypeError('messages must be a dict, event or a list thereof')
        result_tickets = dict()
        for message in messages:
            if not isinstance(message, (dict, scim.Event)):
                raise TypeError('messages must be a dict, '
                                'Event or a list thereof')
            try:
                if isinstance(message, dict):
                    err_msg = 'Could not extract schedule time'
                    if 'nbf' not in message:
                        continue
                    eta = datetime.datetime.fromtimestamp(int(message['nbf']))
                    jti = message.get('jti', 'invalid')
                    err_msg = 'Could not get routing-key'
                    routing_key = message.get('routing-key', 'unknown')
                    err_msg = 'Could not produce message-body'
                    body = json.dumps(
                        dict(
                            filter(lambda x: x[0] != 'routing-key',
                                   message.items())))
                else:
                    # scim.Event
                    err_msg = 'Could not extract schedule time'
                    if not isinstance(message.scheduled, datetime.datetime):
                        continue
                    eta = message.scheduled
                    jti = message.jti or 'invalid'
                    err_msg = 'Could not get routing-key'
                    routing_key = message.key
                    err_msg = 'Could not produce message-body'
                    body = json.dumps(message.get_payload())
                err_msg = 'Could not schedule / produce task'
                result_tickets[jti] = (schedule_message.apply_async(kwargs={
                    'routing_key':
                    routing_key,
                    'body':
                    body
                },
                                                                    eta=eta),
                                       eta)
            except Exception as e:
                raise ClientErrors.MessageFormatError('{0}: {1}'.format(
                    err_msg, e))
        return result_tickets