def _on_close(self, method_frame): LOGGER.warning('Received Channel.Close, closing: %r', method_frame) if not self.connection.is_closed: self._send_method(spec.Channel.CloseOk(), None, False) self._set_state(self.CLOSED) self._cleanup() if method_frame is None: raise exceptions.ChannelClosed(0, 'Not specified') else: raise exceptions.ChannelClosed(method_frame.method.reply_code, method_frame.method.reply_text)
def basic_publish(self, exchange, routing_key, body, properties=None, mandatory=False, immediate=False): """Publish to the channel with the given exchange, routing key and body. For more information on basic_publish and what the parameters do, see: http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.publish :param exchange: The exchange to publish to :type exchange: str or unicode :param routing_key: The routing key to bind on :type routing_key: str or unicode :param body: The message body :type body: str or unicode :param pika.spec.BasicProperties properties: Basic.properties :param bool mandatory: The mandatory flag :param bool immediate: The immediate flag """ if not self.is_open: raise exceptions.ChannelClosed() if immediate: LOGGER.warning('The immediate flag is deprecated in RabbitMQ') if isinstance(body, unicode): body = body.encode('utf-8') properties = properties or spec.BasicProperties() self._send_method(spec.Basic.Publish(exchange=exchange, routing_key=routing_key, mandatory=mandatory, immediate=immediate), (properties, body))
def close(self, reply_code=0, reply_text="Normal Shutdown"): """Will invoke a clean shutdown of the channel with the AMQP Broker. :param int reply_code: The reply code to close the channel with :param str reply_text: The reply text to close the channel with """ LOGGER.info('Channel.close(%s, %s)', reply_code, reply_text) if not self.is_open: raise exceptions.ChannelClosed() # Cancel the generator if it's running if self._generator: self.cancel() # If there are any consumers, cancel them as well if self._consumers: LOGGER.debug('Cancelling %i consumers', len(self._consumers)) for consumer_tag in self._consumers.keys(): self.basic_cancel(consumer_tag=consumer_tag) self._set_state(self.CLOSING) self._rpc(spec.Channel.Close(reply_code, reply_text, 0, 0), None, [spec.Channel.CloseOk]) self._set_state(self.CLOSED) self._cleanup()
def close(self, reply_code=0, reply_text="Normal Shutdown"): if self.is_closed: raise exceptions.ChannelClosed('Already closed: %s' % self) LOGGER.info('Closing channel (%s): %r on %s', reply_code, reply_text, self) for consumer_tag in dictkeys(self._consumers): self.basic_cancel(consumer_tag=consumer_tag) self.is_closed = True return self.rpc(spec.Channel.Close(reply_code, reply_text, 0, 0), [spec.Channel.CloseOk])
def channel_closed(self, channel, reply_code, reply_text): # enter the closed state self.__closed = exceptions.ChannelClosed(reply_code, reply_text) # errback all pending calls for d in self.__calls: d.errback(self.__closed) # close all open queues for consumers in self.__consumers.values(): for c in consumers: c.close(self.__closed) # release references to stored objects self.__calls = set() self.__consumers = {}
def basic_reject(self, delivery_tag=None, requeue=True): """Reject an incoming message. This method allows a client to reject a message. It can be used to interrupt and cancel large incoming messages, or return untreatable messages to their original queue. :param int delivery-tag: The server-assigned delivery tag :param bool requeue: If requeue is true, the server will attempt to requeue the message. If requeue is false or the requeue attempt fails the messages are discarded or dead-lettered. """ if not self.is_open: raise exceptions.ChannelClosed() return self._send_method(spec.Basic.Reject(delivery_tag, requeue))
def close(self, reply_code=0, reply_text="Normal Shutdown"): """Will invoke a clean shutdown of the channel with the AMQP Broker. :param int reply_code: The reply code to close the channel with :param str reply_text: The reply text to close the channel with """ if not self.is_open: raise exceptions.ChannelClosed() LOGGER.info('Channel.close(%s, %s)', self._reply_code, self._reply_text) self._set_state(self.CLOSING) self._reply_code, self._reply_text = reply_code, reply_text LOGGER.debug('Cancelling %i consumers', len(self._consumers)) for consumer_tag in self._consumers.keys(): self.basic_cancel(consumer_tag) self._shutdown()
def basic_consume(self, consumer_callback, queue='', no_ack=False, exclusive=False, consumer_tag=None): """ Sends the AMQP command Basic.Consume to the broker and binds messages for the consumer_tag to the consumer callback. If you do not pass in a consumer_tag, one will be automatically generated for you. Returns the consumer tag. For more information on basic_consume, see: http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.consume """ # If a consumer tag was not passed, create one if not consumer_tag: consumer_tag = 'ctag%i.%i' % (self.channel_number, len(self._consumers)) # Make sure we've not already registered this consumer tag if consumer_tag in self._consumers: raise exceptions.DuplicateConsumerTag(consumer_tag) # The consumer tag has not been used before, add it to our consumers self._consumers[consumer_tag] = consumer_callback # Setup a list for appending frames into self._pending[consumer_tag] = list() # Send our Basic.Consume RPC call try: self.transport.rpc( spec.Basic.Consume(queue=queue, consumer_tag=consumer_tag, no_ack=no_ack, exclusive=exclusive), self.transport._on_event_ok, [spec.Basic.ConsumeOk]) except exceptions.ChannelClosed, e: del (self._consumers[consumer_tag]) del (self._pending[consumer_tag]) raise exceptions.ChannelClosed(e)
def basic_ack(self, delivery_tag=0, multiple=False): """Acknowledge one or more messages. When sent by the client, this method acknowledges one or more messages delivered via the Deliver or Get-Ok methods. When sent by server, this method acknowledges one or more messages published with the Publish method on a channel in confirm mode. The acknowledgement can be for a single message or a set of messages up to and including a specific message. :param int delivery-tag: The server-assigned delivery tag :param bool multiple: If set to True, the delivery tag is treated as "up to and including", so that multiple messages can be acknowledged with a single method. If set to False, the delivery tag refers to a single message. If the multiple field is 1, and the delivery tag is zero, this indicates acknowledgement of all outstanding messages. """ if not self.is_open: raise exceptions.ChannelClosed() return self._send_method(spec.Basic.Ack(delivery_tag, multiple))
def basic_nack(self, delivery_tag=None, multiple=False, requeue=True): """This method allows a client to reject one or more incoming messages. It can be used to interrupt and cancel large incoming messages, or return untreatable messages to their original queue. :param int delivery-tag: The server-assigned delivery tag :param bool multiple: If set to True, the delivery tag is treated as "up to and including", so that multiple messages can be acknowledged with a single method. If set to False, the delivery tag refers to a single message. If the multiple field is 1, and the delivery tag is zero, this indicates acknowledgement of all outstanding messages. :param bool requeue: If requeue is true, the server will attempt to requeue the message. If requeue is false or the requeue attempt fails the messages are discarded or dead-lettered. """ if not self.is_open: raise exceptions.ChannelClosed() return self._send_method(spec.Basic.Nack(delivery_tag, multiple, requeue))
def basic_publish(self, exchange, routing_key, body, properties=None, mandatory=False, immediate=False): """Publish to the channel with the given exchange, routing key and body. Returns a boolean value indicating the success of the operation. For more information on basic_publish and what the parameters do, see: http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.publish :param exchange: The exchange to publish to :type exchange: str or unicode :param routing_key: The routing key to bind on :type routing_key: str or unicode :param body: The message body :type body: str or unicode :param pika.spec.Properties properties: Basic.properties :param bool mandatory: The mandatory flag :param bool immediate: The immediate flag """ if not self.is_open: raise exceptions.ChannelClosed() if immediate: LOGGER.warning('The immediate flag is deprecated in RabbitMQ') properties = properties or spec.BasicProperties() if mandatory: self._response = None if isinstance(body, unicode): body = body.encode('utf-8') if self._confirmation: response = self._rpc( spec.Basic.Publish(exchange=exchange, routing_key=routing_key, mandatory=mandatory, immediate=immediate), None, [spec.Basic.Ack, spec.Basic.Nack], (properties, body)) if mandatory and self._response: response = self._response[0] LOGGER.warning('Message was returned (%s): %s', response.reply_code, response.reply_text) return False if isinstance(response.method, spec.Basic.Ack): return True elif isinstance(response.method, spec.Basic.Nack): return False else: raise ValueError('Unexpected frame type: %r', response) else: self._send_method( spec.Basic.Publish(exchange=exchange, routing_key=routing_key, mandatory=mandatory, immediate=immediate), (properties, body), False) if mandatory: if self._response: response = self._response[0] LOGGER.warning('Message was returned (%s): %s', response.reply_code, response.reply_text) return False return True
def test_channel_closed_repr(self): exc = exceptions.ChannelClosed(200, 'all is swell') self.assertEqual(repr(exc), "ChannelClosed: (200) 'all is swell'")
def test_channel_closed_properties_kwargs(self): exc = exceptions.ChannelClosed(reply_code=9, reply_text='kwargs abcd') self.assertEqual(exc.reply_code, 9) self.assertEqual(exc.reply_text, 'kwargs abcd')
def test_channel_closed_properties_positional_args(self): exc = exceptions.ChannelClosed(9, 'args abcd') self.assertEqual(exc.reply_code, 9) self.assertEqual(exc.reply_text, 'args abcd')
def _validate_connection_and_channel(self): if self.connection.is_closed(): raise exceptions.ConnectionClosed() if self.is_closed: raise exceptions.ChannelClosed()
def _validate_channel_and_callback(self, callback): if not self.is_open: raise exceptions.ChannelClosed() if callback is not None and not is_callable(callback): raise ValueError('callback must be a function or method')
def _on_channel_close(self, channel, reply_code, reply_text): self._evt_closed.set() if self._current_future: self._current_future.set_exception( pika_exceptions.ChannelClosed(reply_code, reply_text))
def _on_close(self, method_frame): LOGGER.warning('Received Channel.Close, closing: %r', method_frame) self._send_method(spec.Channel.CloseOk(), None, False) self._set_state(self.CLOSED) raise exceptions.ChannelClosed(self._reply_code, self._reply_text)