def _publish_and_raises_on_missing_exchange(self, exchange, msg, routing_key=None, timeout=None): """Publisher that raises exception if exchange is missing.""" if not exchange.passive: raise RuntimeError("_publish_and_retry_on_missing_exchange() must " "be called with an passive exchange.") try: self._publish(exchange, msg, routing_key=routing_key, timeout=timeout) return except self.connection.channel_errors as exc: if exc.code == 404: # NOTE(noelbk/sileht): # If rabbit dies, the consumer can be disconnected before the # publisher sends, and if the consumer hasn't declared the # queue, the publisher's will send a message to an exchange # that's not bound to a queue, and the message wll be lost. # So we set passive=True to the publisher exchange and catch # the 404 kombu ChannelError and retry until the exchange # appears raise rpc_amqp.AMQPDestinationNotFound( "exchange %s doesn't exists" % exchange.name) raise
def _publish_and_retry_on_missing_exchange(self, exchange, msg, routing_key=None, timeout=None): """Publisher that retry if the exchange is missing. """ if not exchange.passive: raise RuntimeError("_publish_and_retry_on_missing_exchange() must " "be called with an passive exchange.") # TODO(sileht): use @retrying # NOTE(sileht): no need to wait the application expect a response # before timeout is exshauted duration = (timeout if timeout is not None else self.kombu_reconnect_timeout) timer = rpc_common.DecayingTimer(duration=duration) timer.start() while True: try: self._publish(exchange, msg, routing_key=routing_key, timeout=timeout) return except self.connection.channel_errors as exc: # NOTE(noelbk/sileht): # If rabbit dies, the consumer can be disconnected before the # publisher sends, and if the consumer hasn't declared the # queue, the publisher's will send a message to an exchange # that's not bound to a queue, and the message wll be lost. # So we set passive=True to the publisher exchange and catch # the 404 kombu ChannelError and retry until the exchange # appears if exc.code == 404 and timer.check_return() > 0: LOG.info( _LI("The exchange %(exchange)s to send to " "%(routing_key)s doesn't exist yet, " "retrying...") % { 'exchange': exchange.name, 'routing_key': routing_key }) time.sleep(0.25) continue elif exc.code == 404: msg = _("The exchange %(exchange)s to send to " "%(routing_key)s still doesn't exist after " "%(duration)s sec abandoning...") % { 'duration': duration, 'exchange': exchange.name, 'routing_key': routing_key } LOG.info(msg) raise rpc_amqp.AMQPDestinationNotFound(msg) raise