class Method(Messenger): """ QMF method. :ivar name: The method name. :type name: str :ivar arguments: The method arguments. :type arguments: dict :ivar connection: A broker connection. :type connection: Connection :ivar session: An AMQP session. :type session: qpid.messaging.Session. :ivar sender: A message sender. :type sender: qpid.messaging.Sender :ivar receiver: A message sender. :type receiver: qpid.messaging.Receiver """ def __init__(self, url, name, arguments): """ :param url: The broker url. :type url: str :param name: The method name. :type name: str :param arguments: The method arguments. :type arguments: dict """ super(Method, self).__init__(url) self.name = name self.arguments = arguments self.connection = Connection(url) self.session = None self.sender = None self.receiver = None self.reply_to = REPLY_TO % uuid4() @property def content(self): return { '_object_id': OBJECT_ID, '_method_name': self.name, '_arguments': self.arguments } @property def properties(self): return { 'qmf.opcode': '_method_request', 'x-amqp-0-10.app-id': 'qmf2', 'method': 'request' } def is_open(self): """ Get whether the method is open. :return: True if open. :rtype: bool """ return self.sender is not None def open(self): """ Open a connection and get a sender and receiver. """ if self.is_open(): # already open return self.connection.open() self.session = self.connection.session() self.sender = self.session.sender(ADDRESS) self.receiver = self.session.receiver(self.reply_to) def repair(self): """ Repair the connection and get a sender and receiver. """ self.close() self.connection.close() self.connection.open() self.session = self.connection.session() self.sender = self.session.sender(ADDRESS) self.receiver = self.session.receiver(self.reply_to) def close(self): """ Close the sender and receiver. """ session = self.session self.session = None sender = self.sender self.sender = None receiver = self.receiver self.receiver = None try: receiver.close() except Exception: pass try: sender.close() except Exception: pass try: session.close() except Exception: pass def on_reply(self, reply): """ Process the QMF reply. :param reply: The reply. :type reply: Message :raise: Error on failures. """ opcode = reply.properties['qmf.opcode'] if opcode != '_exception': # succeeded return body = reply.content values = body['_values'] code = values['error_code'] description = values['error_text'] if code == EEXIST: return raise Error(description, code) @reliable def __call__(self): """ Invoke the method. :raise: Error on failure. """ self.open() try: request = Message( content=self.content, reply_to=self.reply_to, properties=self.properties, correlation_id=utf8(uuid4()), subject=SUBJECT) self.sender.send(request) reply = self.receiver.fetch() self.session.acknowledge() self.on_reply(reply) finally: self.close()
class Sender(BaseSender): """ An AMQP message sender. """ def __init__(self, url): """ :param url: The broker url. :type url: str """ BaseSender.__init__(self, url) self.connection = Connection(url) self.session = None def is_open(self): """ Get whether the sender has been opened. :return: True if open. :rtype bool """ return self.session is not None @reliable def open(self): """ Open the sender. """ if self.is_open(): # already opened return self.connection.open() self.session = self.connection.session() def repair(self): """ Repair the sender. """ self.close() self.connection.close() self.connection.open() self.session = self.connection.session() def close(self): """ Close the reader. """ session = self.session self.session = None try: session.close() except Exception: pass @reliable def send(self, address, content, ttl=None): """ Send a message. :param address: An AMQP address. :type address: str :param content: The message content :type content: buf :param ttl: Time to Live (seconds) :type ttl: float """ sender = self.session.sender(address) try: message = Message(content=content, durable=self.durable, ttl=ttl) sender.send(message) log.debug('sent (%s)', address) finally: sender.close()
def test_session(self): url = TEST_URL c = Connection(url) c._impl = Mock() session = c.session() self.assertEqual(session, c._impl.session.return_value)
def test_session(self): url = TEST_URL c = Connection(url) c._impl = Mock() session = c.session() self.assertEqual(session, c._impl.session.return_value)
class Reader(BaseReader): """ An AMQP message reader. :ivar receiver: An AMQP receiver to read. :type receiver: qpid.messaging.Receiver """ def __init__(self, node, url): """ :param node: The AMQP node to read. :type node: gofer.messaging.adapter.model.Node :param url: The broker url. :type url: str :see: gofer.messaging.adapter.url.URL """ BaseReader.__init__(self, node, url) self.connection = Connection(url) self.session = None self.receiver = None def is_open(self): """ Get whether the messenger has been opened. :return: True if open. :rtype bool """ return self.receiver is not None @reliable def open(self): """ Open the reader. :raise: NotFound """ if self.is_open(): # already open return self.connection.open() self.session = self.connection.session() self.receiver = self.session.receiver(self.node.address) def repair(self): """ Repair the reader. :raise: NotFound """ self.close() self.connection.close() self.connection.open() self.session = self.connection.session() self.receiver = self.session.receiver(self.node.address) def close(self): """ Close the reader. """ receiver = self.receiver self.receiver = None session = self.session self.session = None try: receiver.close() except Exception: pass try: session.close() except Exception: pass @reliable def get(self, timeout=None): """ Get the next message from the queue. :param timeout: The read timeout in seconds. :type timeout: int :return: The next message or None. :rtype: Message """ try: impl = self.receiver.fetch(timeout or NO_DELAY) return Message(self, impl, impl.content) except Empty: pass @reliable def ack(self, message): """ Acknowledge all messages received on the session. :param message: The message to acknowledge. :type message: qpid.messaging.Message """ self.session.acknowledge(message=message) @reliable def reject(self, message, requeue=True): """ Reject the specified message. :param message: The message to reject. :type message: qpid.messaging.Message :param requeue: Requeue the message or discard it. :type requeue: bool """ if requeue: disposition = Disposition(RELEASED) else: disposition = Disposition(REJECTED) self.session.acknowledge(message=message, disposition=disposition)
class Sender(BaseSender): """ An AMQP message sender. """ def __init__(self, url): """ :param url: The broker url. :type url: str """ BaseSender.__init__(self, url) self.connection = Connection(url) self.session = None def is_open(self): """ Get whether the sender has been opened. :return: True if open. :rtype bool """ return self.session is not None @reliable def open(self): """ Open the sender. """ if self.is_open(): # already opened return self.connection.open() self.session = self.connection.session() def repair(self): """ Repair the sender. """ self.close() self.connection.close() self.connection.open() self.session = self.connection.session() def close(self): """ Close the reader. """ session = self.session self.session = None try: session.close() except Exception: pass @reliable def send(self, address, content, ttl=None): """ Send a message. :param address: An AMQP address. :type address: str :param content: The message content :type content: buf :param ttl: Time to Live (seconds) :type ttl: float """ sender = self.session.sender(address) try: message = Message(content=content, durable=self.durable, ttl=ttl) sender.send(message) log.debug('sent (%s)', address) finally: sender.close()