from typing import Callable, Generic, Optional, TypeVar from amqpstorm import Channel from amqpworker.easyqueue.connection import AMQPConnection from amqpworker.easyqueue.exceptions import UndecodableMessageException T = TypeVar("T") class AMQPMessage(Generic[T]): __slots__ = ( "connection", "channel", "queue_name", "serialized_data", "delivery_tag", "_properties", "_deserialization_method", "_deserialized_data", "_queue", ) def __init__( self, connection: AMQPConnection, channel: Channel, queue_name: str, serialized_data: bytes, delivery_tag: int, properties: dict, deserialization_method: Callable[[bytes], T], queue, ) -> None: self.queue_name = queue_name self.serialized_data = serialized_data self.delivery_tag = delivery_tag self.connection = connection self.channel = channel self._properties = properties self._deserialization_method = deserialization_method self._deserialized_data: Optional[T] = None self._queue = queue @property def deserialized_data(self) -> T: if self._deserialized_data: return self._deserialized_data try: self._deserialized_data = self._deserialization_method( self.serialized_data ) except ValueError as e: raise UndecodableMessageException( "msg couldn't be decoded as JSON" ) from e return self._deserialized_data def __eq__(self, other): if not isinstance(other, self.__class__): return False for attr in self.__slots__: if attr.startswith("__"): continue if getattr(self, attr) != getattr(other, attr): return False return True def ack(self): return self.channel.basic.ack(self.delivery_tag) def reject(self, requeue=False): return self.channel.basic.reject( delivery_tag=self.delivery_tag, requeue=requeue ) def requeue(self): self.channel.basic.ack(self.delivery_tag) self.channel.basic.publish(body=self.serialized_data, routing_key=self.queue_name, properties=self._properties, mandatory=False, immediate=False)