# Path: microcosm_pubsub/errors.py
# class IgnoreMessage(Exception):
#     """
#     Do not processing a message and do not count it for statistics.
# 
#     Indicates that message was not processable by the daemon.
# 
#     """
#     def __init__(self, reason, extra=None):
#         super().__init__(reason)
#         self.extra = extra or dict()
# 
# class Nack(Exception):
#     """
#     Retry the message after a configured number of seconds.
# 
#     Note that retry behavior is contingent on both the backoff policy
#     and the SQS dead letter queue (DLQ) configuration, if any.
# 
#     """
#     def __init__(self, visibility_timeout_seconds):
#         self.visibility_timeout_seconds = visibility_timeout_seconds
# 
#     def __repr__(self):
#         return "Nack({})".format(self.visibility_timeout_seconds)
# 
# class SkipMessage(Exception):
#     """
#     Stop processing a message and do not retry processing.
# 
#     Indicates that message content failed a precondition within a handler.
# 
#     """
#     def __init__(self, reason, extra=None):
#         super().__init__(reason)
#         self.extra = extra or dict()
# 
# class TTLExpired(Exception):
#     """
#     Control-flow exception to skip messages in infinite loop.
# 
#     """
#     def __init__(self, reason=None, extra=None):
#         super().__init__(reason)
#         self.extra = extra or dict()
# 
# Path: microcosm_pubsub/message.py
# class SQSMessage:
#     """
#     SQS message wrapper.
# 
#     """
#     def __init__(self,
#                  consumer,
#                  content,
#                  media_type,
#                  message_id,
#                  receipt_handle,
#                  topic_arn=None,
#                  approximate_receive_count=None,
#                  handler=None):
#         self.consumer = consumer
#         self.content = content
#         self.media_type = media_type
#         self.message_id = message_id
#         self.receipt_handle = receipt_handle
#         self.topic_arn = topic_arn
#         self.approximate_receive_count = approximate_receive_count
#         self.handler = handler
# 
#     def ack(self):
#         """
#         Acknowledge this message was processed successfully.
# 
#         """
#         self.consumer.ack(self)
# 
#     def nack(self, visibility_timeout_seconds=None):
#         """
#         Acknowledge this message was NOT processed successfully.
# 
#         """
#         self.consumer.nack(self, visibility_timeout_seconds)
# 
#     @property
#     def opaque_data(self):
#         if not self.content:
#             return dict()
#         return self.content.get("opaque_data", {})
# 
#     @property
#     def ttl(self):
#         if TTL_KEY not in self.opaque_data:
#             return None
#         return int(self.opaque_data[TTL_KEY])
# 
#     @property
#     def uri(self):
#         if not self.content:
#             return None
#         return self.content.get("uri")
# 
# Path: microcosm_pubsub/sentry.py
# class SentryConfigPubsub:
#     dsn: Optional[str] = None
#     enabled: bool = False
#     client: Optional[Any] = None
#     tag_mapping: Dict[str, str] = field(default_factory=dict)
#     user_id_key: Optional[str] = None


from dataclasses import dataclass, field
from enum import Enum, unique
from logging import DEBUG, INFO, WARNING
from sys import exc_info
from typing import (
    Any,
    Dict,
    Optional,
    Tuple,
)
from microcosm.opaque import Opaque
from microcosm_pubsub.errors import (
    IgnoreMessage,
    Nack,
    SkipMessage,
    TTLExpired,
)
from microcosm_pubsub.message import SQSMessage
from microcosm_pubsub.sentry import SentryConfigPubsub
        from sentry_sdk import capture_exception
        from sentry_sdk import configure_scope
class MessageHandlingResult:
    media_type: str
    result: MessageHandlingResultType
    exc_info: Optional[Tuple[Any, Any, Any]] = None
    extra: Dict[str, str] = field(default_factory=dict)
    elapsed_time: Optional[float] = None
    handle_start_time: Optional[float] = None
    retry_timeout_seconds: Optional[int] = None

    @classmethod
    def invoke(cls, handler, message: SQSMessage):
        try:
            success = handler(message.content)
            return cls.from_result(message, bool(success))
        except Exception as error:
            return cls.from_error(message, error)

    @classmethod
    def from_result(cls, message: SQSMessage, success: bool):
        if success:
            result = MessageHandlingResultType.SUCCEEDED
        else:
            result = MessageHandlingResultType.SKIPPED

        return cls(
            media_type=message.media_type,
            result=result,
        )

    @classmethod

# Path: microcosm_pubsub/errors.py
# class IgnoreMessage(Exception):
#     """
#     Do not processing a message and do not count it for statistics.
# 
#     Indicates that message was not processable by the daemon.
# 
#     """
#     def __init__(self, reason, extra=None):
#         super().__init__(reason)
#         self.extra = extra or dict()
# 
# class Nack(Exception):
#     """
#     Retry the message after a configured number of seconds.
# 
#     Note that retry behavior is contingent on both the backoff policy
#     and the SQS dead letter queue (DLQ) configuration, if any.
# 
#     """
#     def __init__(self, visibility_timeout_seconds):
#         self.visibility_timeout_seconds = visibility_timeout_seconds
# 
#     def __repr__(self):
#         return "Nack({})".format(self.visibility_timeout_seconds)
# 
# class SkipMessage(Exception):
#     """
#     Stop processing a message and do not retry processing.
# 
#     Indicates that message content failed a precondition within a handler.
# 
#     """
#     def __init__(self, reason, extra=None):
#         super().__init__(reason)
#         self.extra = extra or dict()
# 
# class TTLExpired(Exception):
#     """
#     Control-flow exception to skip messages in infinite loop.
# 
#     """
#     def __init__(self, reason=None, extra=None):
#         super().__init__(reason)
#         self.extra = extra or dict()
# 
# Path: microcosm_pubsub/message.py
# class SQSMessage:
#     """
#     SQS message wrapper.
# 
#     """
#     def __init__(self,
#                  consumer,
#                  content,
#                  media_type,
#                  message_id,
#                  receipt_handle,
#                  topic_arn=None,
#                  approximate_receive_count=None,
#                  handler=None):
#         self.consumer = consumer
#         self.content = content
#         self.media_type = media_type
#         self.message_id = message_id
#         self.receipt_handle = receipt_handle
#         self.topic_arn = topic_arn
#         self.approximate_receive_count = approximate_receive_count
#         self.handler = handler
# 
#     def ack(self):
#         """
#         Acknowledge this message was processed successfully.
# 
#         """
#         self.consumer.ack(self)
# 
#     def nack(self, visibility_timeout_seconds=None):
#         """
#         Acknowledge this message was NOT processed successfully.
# 
#         """
#         self.consumer.nack(self, visibility_timeout_seconds)
# 
#     @property
#     def opaque_data(self):
#         if not self.content:
#             return dict()
#         return self.content.get("opaque_data", {})
# 
#     @property
#     def ttl(self):
#         if TTL_KEY not in self.opaque_data:
#             return None
#         return int(self.opaque_data[TTL_KEY])
# 
#     @property
#     def uri(self):
#         if not self.content:
#             return None
#         return self.content.get("uri")
# 
# Path: microcosm_pubsub/sentry.py
# class SentryConfigPubsub:
#     dsn: Optional[str] = None
#     enabled: bool = False
#     client: Optional[Any] = None
#     tag_mapping: Dict[str, str] = field(default_factory=dict)
#     user_id_key: Optional[str] = None


# Path: microcosm_pubsub/result.py
from dataclasses import dataclass, field
from enum import Enum, unique
from logging import DEBUG, INFO, WARNING
from sys import exc_info
from typing import (
    Any,
    Dict,
    Optional,
    Tuple,
)
from microcosm.opaque import Opaque
from microcosm_pubsub.errors import (
    IgnoreMessage,
    Nack,
    SkipMessage,
    TTLExpired,
)
from microcosm_pubsub.message import SQSMessage
from microcosm_pubsub.sentry import SentryConfigPubsub
        from sentry_sdk import capture_exception
        from sentry_sdk import configure_scope

class MessageHandlingResult:
    media_type: str
    result: MessageHandlingResultType
    exc_info: Optional[Tuple[Any, Any, Any]] = None
    extra: Dict[str, str] = field(default_factory=dict)
    elapsed_time: Optional[float] = None
    handle_start_time: Optional[float] = None
    retry_timeout_seconds: Optional[int] = None

    @classmethod
    def invoke(cls, handler, message: SQSMessage):
        try:
            success = handler(message.content)
            return cls.from_result(message, bool(success))
        except Exception as error:
            return cls.from_error(message, error)

    @classmethod
    def from_result(cls, message: SQSMessage, success: bool):
        if success:
            result = MessageHandlingResultType.SUCCEEDED
        else:
            result = MessageHandlingResultType.SKIPPED

        return cls(
            media_type=message.media_type,
            result=result,
        )

    @classmethod

    def from_error(cls, message: SQSMessage, error: Exception, **kwargs):