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)
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)
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))
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', ) }
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, ) }
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