"""Amazon SQS connector.""" from boto import sqs from boto.sqs.jsonmessage import JSONMessage from label_copy_export.connectors.loggly import get_current_logger from label_copy_export.connectors.sentry import sentry_client from label_copy_export.utils.dot_dict import DotDict CORRELATION_ID_ATTRIBUTE = 'Correlation-Id' APPROXIMATE_RECEIVE_COUNT_ATTRIBUTE = 'ApproximateReceiveCount' FEATURE_FLAG_USER_CONTEXT_ATTRIBUTE = 'feature_flag_user_context' class JSONMessageExt(JSONMessage): """Wrapper for SQS Messages for a logger with Correlation-Id.""" def __init__(self, *args, **kwargs): """Create new instance of JSONMessageExt.""" super(JSONMessageExt, self).__init__(*args, **kwargs) self._context = DotDict() @property def context(self): """Store an additional context for message (e.g. logging adapter). Returns: DotDict: an object that holds message context """ return self._context @property def correlation_id(self): """Get Correlation-Id extracted from message attributes. Returns: str: correlation Id """ correlation_attribute = self.message_attributes.get( CORRELATION_ID_ATTRIBUTE, {}) return correlation_attribute.get('string_value', None) @property def logger(self): """Get logging adapter for current message. Returns: OwsLoggingAdapter: Logging adapter with Correlation-Id, extracted from SQS message attributes. """ if not self.context.logger: self.context.logger = get_current_logger(self.correlation_id) return self.context.logger @property def receive_count(self): """Get approximate message receive count. Returns: int: approximate number of times the message has been received """ count = self.attributes.get(APPROXIMATE_RECEIVE_COUNT_ATTRIBUTE, 0) return int(count) @property def feature_flag_user_context(self): """Get feature_flag_user_context extracted from message attributes. Returns: str: feature flag user context """ feature_flag_user_context_attribute = self.message_attributes.get( FEATURE_FLAG_USER_CONTEXT_ATTRIBUTE, {}) return feature_flag_user_context_attribute.get('string_value', None) def get_connection( region='us-east-1', access_key_id=None, secret_access_key=None): """Get connection to Amazon SQS services. Args: region (str): AWS Region access_key_id (str): AWS Access key ID secret_access_key (str): Corresponding AWS Secret Access Key Returns: SQSConnection: instance of SQSConnection class """ connection = sqs.connect_to_region( region, aws_access_key_id=access_key_id, aws_secret_access_key=secret_access_key) return connection def get_queue(queue_name, message_class=JSONMessageExt, sqs_connection=None): """Get Amazon SQS queue. Args: queue_name (str): Name of the SQS queue to get message_class (class): Optional message class to wrap the received messages sqs_connection (boto.sqs.connection.SQSConnection): Optional existing SQS connection object Returns: Queue: Instance of Amazon SQS queue """ try: connection = sqs_connection if sqs_connection else get_connection() queue = connection.get_queue(queue_name) if queue: queue.set_message_class(message_class) return queue except: if sentry_client: sentry_client.captureException() return None