Esempio n. 1
0
def deliver(channel_type, rendered_message, message):
    u"""
    Deliver a message via a particular channel.

    Args:
        channel_type (ChannelType): The channel type to deliver the channel over.
        rendered_message (object): Each attribute of this object contains rendered content.
        message (Message): The message that is being sent.

    Raises:
        :class:`.UnsupportedChannelError`: If no channel of the requested channel type is available.

    """
    channel = channels().get(channel_type)
    if not channel:
        raise UnsupportedChannelError(
            u'No implementation for channel {channel_type} registered. Available channels are: {channels}'
            .format(channel_type=channel_type,
                    channels=u', '.join(
                        six.text_type(registered_channel_type)
                        for registered_channel_type in channels())))
    logger = message.get_message_specific_logger(LOG)

    timeout_seconds = getattr(settings, u'ACE_DEFAULT_EXPIRATION_DELAY', 120)
    start_time = get_current_time()
    default_expiration_time = start_time + datetime.timedelta(
        seconds=timeout_seconds)
    max_expiration_time = start_time + datetime.timedelta(
        seconds=MAX_EXPIRATION_DELAY)
    expiration_time = min(max_expiration_time, message.expiration_time
                          or default_expiration_time)

    while get_current_time() < expiration_time:
        logger.debug(u'Attempting delivery of message')
        try:
            channel.deliver(message, rendered_message)
        except RecoverableChannelDeliveryError as delivery_error:
            num_seconds = (delivery_error.next_attempt_time -
                           get_current_time()).total_seconds()
            logger.debug(u'Encountered a recoverable delivery error.')
            if delivery_error.next_attempt_time > expiration_time:
                logger.debug(
                    u'Message will expire before delivery can be reattempted, aborting.'
                )
                break
            elif num_seconds > 0:
                logger.debug(u'Sleeping for %d seconds.', num_seconds)
                time.sleep(num_seconds)
                message.report(
                    u'{channel_type}_delivery_retried'.format(
                        channel_type=channel_type), num_seconds)
        else:
            message.report(
                u'{channel_type}_delivery_succeeded'.format(
                    channel_type=channel_type), True)
            return

    message.report(
        u'{channel_type}_delivery_expired'.format(channel_type=channel_type),
        get_current_time() - start_time)
Esempio n. 2
0
def deliver(channel, rendered_message, message):
    """
    Deliver a message via a particular channel.

    Args:
        channel (Channel): The channel to deliver the message over.
        rendered_message (object): Each attribute of this object contains rendered content.
        message (Message): The message that is being sent.

    Raises:
        :class:`.UnsupportedChannelError`: If no channel of the requested channel type is available.

    """
    logger = message.get_message_specific_logger(LOG)
    channel_type = channel.channel_type

    timeout_seconds = getattr(settings, 'ACE_DEFAULT_EXPIRATION_DELAY', 120)
    start_time = get_current_time()
    default_expiration_time = start_time + datetime.timedelta(
        seconds=timeout_seconds)
    max_expiration_time = start_time + datetime.timedelta(
        seconds=MAX_EXPIRATION_DELAY)
    expiration_time = min(max_expiration_time, message.expiration_time
                          or default_expiration_time)

    logger.debug('Attempting delivery of message')
    while get_current_time() < expiration_time:
        try:
            channel.deliver(message, rendered_message)
        except RecoverableChannelDeliveryError as delivery_error:
            num_seconds = (delivery_error.next_attempt_time -
                           get_current_time()).total_seconds()
            logger.debug('Encountered a recoverable delivery error.')
            if delivery_error.next_attempt_time > expiration_time:
                logger.debug(
                    'Message will expire before delivery can be reattempted, aborting.'
                )
                break
            logger.debug(
                'Sleeping for %d seconds before reattempting delivery of message.',
                num_seconds)
            time.sleep(num_seconds)
            message.report(f'{channel_type}_delivery_retried', num_seconds)
        else:
            message.report(f'{channel_type}_delivery_succeeded', True)
            return

    delivery_expired_report = f'{channel_type}_delivery_expired'
    logger.debug(delivery_expired_report)
    message.report(delivery_expired_report, get_current_time() - start_time)
Esempio n. 3
0
    def _handle_error_response(self, response):
        u"""
        Handle an error response from SailThru, either by retrying or failing
        with an appropriate exception.

        Arguments:
            response: The HTTP response recieved from SailThru.
        """
        error = response.get_error()
        error_code = error.get_error_code()
        error_message = error.get_message()
        http_status_code = response.get_status_code()
        if error_code in RecoverableErrorCodes:
            next_attempt_time = None
            if error_code == RecoverableErrorCodes.RATE_LIMIT:
                next_attempt_time = self._get_rate_limit_reset_time(
                    sailthru_response=response)

            if next_attempt_time is None:
                # Sailthru advises waiting "a moment" and then trying again.
                next_attempt_time = get_current_time() + timedelta(
                    seconds=NEXT_ATTEMPT_DELAY_SECONDS + random.uniform(-2, 2))

            raise RecoverableChannelDeliveryError(
                u'Recoverable Sailthru error (error_code={error_code} status_code={http_status_code}): '
                u'{message}'.format(error_code=error_code,
                                    http_status_code=http_status_code,
                                    message=error_message), next_attempt_time)
        else:
            raise FatalChannelDeliveryError(
                u'Fatal Sailthru error (error_code={error_code} status_code={http_status_code}): '
                u'{message}'.format(error_code=error_code,
                                    http_status_code=http_status_code,
                                    message=error_message))
Esempio n. 4
0
 def setUp(self):
     self.msg_kwargs = {
         u'app_label': u'test_app_label',
         u'name': u'test_message',
         u'expiration_time': get_current_time(),
         u'context': {
             u'key1': u'value1',
             u'key2': u'value2',
         },
         u'recipient': Recipient(username=u'me', )
     }
Esempio n. 5
0
 def setUp(self):
     self.msg_kwargs = {
         'app_label': 'test_app_label',
         'name': 'test_message',
         'expiration_time': get_current_time(),
         'context': {
             'key1': 'value1',
             'key2': 'value2',
         },
         'recipient': Recipient(lms_user_id=123, )
     }
Esempio n. 6
0
    def _handle_error_response(self, response, message, exception):
        """
        Handle an error response from Braze, either by retrying or failing
        with an appropriate exception.

        Arguments:
            response: The HTTP response received from Braze.
            message: An error message from Braze.
            exception: The exception that triggered this error.
        """
        if response.status_code == 429 or 500 <= response.status_code < 600:
            next_attempt_time = get_current_time() + timedelta(
                seconds=NEXT_ATTEMPT_DELAY_SECONDS + random.uniform(-2, 2))
            raise RecoverableChannelDeliveryError(
                'Recoverable Braze error (status_code={http_status_code}): {message}'
                .format(http_status_code=response.status_code,
                        message=message), next_attempt_time) from exception

        raise FatalChannelDeliveryError(
            'Fatal Braze error (status_code={http_status_code}): {message}'.
            format(http_status_code=response.status_code,
                   message=message)) from exception