def send_request(self, multipart_message): envelope = multipart_message[zmq_names.MULTIPART_IDX_ENVELOPE] LOG.info(_LI("Envelope: %s") % envelope) target = envelope[zmq_names.FIELD_TARGET] dealer_socket, hosts = self._check_hosts_connections(target) if not dealer_socket.connections: # NOTE(ozamiatin): Here we can provide # a queue for keeping messages to send them later # when some listener appears. However such approach # being more reliable will consume additional memory. LOG.warning( _LW("Request %s was dropped because no connection") % envelope[zmq_names.FIELD_MSG_TYPE]) return self.reply_receiver.track_socket(dealer_socket.handle) LOG.info( _LI("Sending message %(message)s to a target %(target)s") % { "message": envelope[zmq_names.FIELD_MSG_ID], "target": envelope[zmq_names.FIELD_TARGET] }) if envelope[zmq_names.FIELD_MSG_TYPE] in zmq_names.MULTISEND_TYPES: for _ in range(dealer_socket.connections_count()): self._send_request(dealer_socket, multipart_message) else: self._send_request(dealer_socket, multipart_message)
def __init__(self, conf, context, matchmaker): self.conf = conf self.context = context super(UniversalQueueProxy, self).__init__() self.matchmaker = matchmaker self.poller = zmq_async.get_poller(zmq_concurrency='native') self.fe_router_socket = zmq_socket.ZmqRandomPortSocket( conf, context, zmq.ROUTER) self.be_router_socket = zmq_socket.ZmqRandomPortSocket( conf, context, zmq.ROUTER) self.poller.register(self.fe_router_socket.handle, self._receive_in_request) self.poller.register(self.be_router_socket.handle, self._receive_in_request) self.fe_router_address = zmq_address.combine_address( self.conf.rpc_zmq_host, self.fe_router_socket.port) self.be_router_address = zmq_address.combine_address( self.conf.rpc_zmq_host, self.fe_router_socket.port) self.pub_publisher = zmq_pub_publisher.PubPublisherProxy( conf, matchmaker) self.matchmaker.register_publisher( (self.pub_publisher.host, self.fe_router_address)) LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Run PUB publisher"), {"pub": self.pub_publisher.host, "router": self.fe_router_address}) self.matchmaker.register_router(self.be_router_address) LOG.info(_LI("[Backend ROUTER:%(router)s] Run ROUTER"), {"router": self.be_router_address})
def send_request(self, multipart_message): envelope = multipart_message[zmq_names.MULTIPART_IDX_ENVELOPE] LOG.info(_LI("Envelope: %s") % envelope) target = envelope[zmq_names.FIELD_TARGET] dealer_socket, hosts = self._check_hosts_connections(target) if not dealer_socket.connections: # NOTE(ozamiatin): Here we can provide # a queue for keeping messages to send them later # when some listener appears. However such approach # being more reliable will consume additional memory. LOG.warning(_LW("Request %s was dropped because no connection") % envelope[zmq_names.FIELD_MSG_TYPE]) return self.reply_receiver.track_socket(dealer_socket.handle) LOG.info(_LI("Sending message %(message)s to a target %(target)s") % {"message": envelope[zmq_names.FIELD_MSG_ID], "target": envelope[zmq_names.FIELD_TARGET]}) if envelope[zmq_names.FIELD_MSG_TYPE] in zmq_names.MULTISEND_TYPES: for _ in range(dealer_socket.connections_count()): self._send_request(dealer_socket, multipart_message) else: self._send_request(dealer_socket, multipart_message)
def _redirect_reply(self, reply): LOG.info(_LI("Reply proxy %s") % reply) if reply[zmq_names.IDX_REPLY_TYPE] == zmq_names.ACK_TYPE: LOG.info(_LI("Acknowledge dropped %s") % reply) return LOG.info(_LI("<- Redirecting reply to ROUTER: reply: %s") % reply[zmq_names.IDX_REPLY_BODY:]) self.router_socket.send_multipart(reply[zmq_names.IDX_REPLY_BODY:])
def __init__(self, conf, context, matchmaker): super(RouterProxy, self).__init__(conf, context, matchmaker) LOG.info(_LI("Polling at ROUTER proxy")) self.dealer_publisher \ = zmq_dealer_publisher_proxy.DealerPublisherProxy( conf, matchmaker, self.poller) self.matchmaker.register_router(self.router_address) LOG.info(_LI("ROUTER:%(router)s] Run ROUTER publisher"), {"router": self.router_address})
def _update_records(self): self.matchmaker.register_publisher( (self.publisher_address, self.fe_router_address), expire=self.conf.zmq_target_expire) LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Update PUB publisher"), {"pub": self.publisher_address, "router": self.fe_router_address}) self.matchmaker.register_router(self.be_router_address, expire=self.conf.zmq_target_expire) LOG.info(_LI("[Backend ROUTER:%(router)s] Update ROUTER"), {"router": self.be_router_address})
def __init__(self, conf, context, matchmaker): super(PublisherProxy, self).__init__(conf, context, matchmaker) LOG.info(_LI("Polling at PUBLISHER proxy")) self.pub_publisher = zmq_pub_publisher.PubPublisherProxy( conf, matchmaker) self.matchmaker.register_publisher( (self.pub_publisher.host, self.router_address)) LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Run PUB publisher"), {"pub": self.pub_publisher.host, "router": self.router_address})
def reply(self, reply=None, failure=None, log_failure=True): if not self.msg_id: # NOTE(Alexei_987) not sending reply, if msg_id is empty # because reply should not be expected by caller side return # NOTE(sileht): return without using a connection if possible if (self.reply_q and not self._obsolete_reply_queues.reply_q_valid(self.reply_q, self.msg_id)): return # NOTE(sileht): we read the configuration value from the driver # to be able to backport this change in previous version that # still have the qpid driver duration = self.listener.driver.missing_destination_retry_timeout timer = rpc_common.DecayingTimer(duration=duration) timer.start() first_reply_sent = False while True: try: with self.listener.driver._get_connection( rpc_common.PURPOSE_SEND) as conn: if self.listener.driver.send_single_reply: self._send_reply(conn, reply, failure, log_failure=log_failure, ending=True) else: if not first_reply_sent: self._send_reply(conn, reply, failure, log_failure=log_failure) first_reply_sent = True self._send_reply(conn, ending=True) return except rpc_amqp.AMQPDestinationNotFound: if timer.check_return() > 0: LOG.info(_LI("The reply %(msg_id)s cannot be sent " "%(reply_q)s reply queue don't exist, " "retrying...") % { 'msg_id': self.msg_id, 'reply_q': self.reply_q}) time.sleep(0.25) else: self._obsolete_reply_queues.add(self.reply_q, self.msg_id) LOG.info(_LI("The reply %(msg_id)s cannot be sent " "%(reply_q)s reply queue don't exist after " "%(duration)s sec abandoning...") % { 'msg_id': self.msg_id, 'reply_q': self.reply_q, 'duration': duration}) return
def _update_records(self): self.matchmaker.register_publisher( (self.publisher_address, self.fe_router_address), expire=self.conf.zmq_target_expire) LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Update PUB publisher"), { "pub": self.publisher_address, "router": self.fe_router_address }) self.matchmaker.register_router(self.be_router_address, expire=self.conf.zmq_target_expire) LOG.info(_LI("[Backend ROUTER:%(router)s] Update ROUTER"), {"router": self.be_router_address})
def __init__(self, conf, context, queue, matchmaker): super(OutgoingQueueProxy, self).__init__(conf, context) self.queue = queue self.matchmaker = matchmaker self.publisher = zmq_dealer_publisher.DealerPublisher( conf, matchmaker) LOG.info(_LI("Polling at outgoing proxy ..."))
def register(self, proxy, in_addr, zmq_type_in, in_bind=True, subscribe=None): LOG.info(_LI("Registering reactor")) if zmq_type_in not in (zmq.PULL, zmq.SUB): raise RPCException("Bad input socktype") # Items push in. inq = ZmqSocket(in_addr, zmq_type_in, bind=in_bind, subscribe=subscribe) self.proxies[inq] = proxy self.sockets.append(inq) LOG.info(_LI("In reactor registered"))
def create_consumer(self, topic, proxy, fanout=False): # Register with matchmaker. _get_matchmaker().register(topic, CONF.rpc_zmq_host) # Subscription scenarios if fanout: sock_type = zmq.SUB subscribe = ('', fanout)[type(fanout) == str] topic = 'fanout~' + topic.split('.', 1)[0] else: sock_type = zmq.PULL subscribe = None topic = '.'.join((topic.split('.', 1)[0], CONF.rpc_zmq_host)) if topic in self.topics: LOG.info(_LI("Skipping topic registration. Already registered.")) return # Receive messages from (local) proxy inaddr = "ipc://%s/zmq_topic_%s" % \ (CONF.rpc_zmq_ipc_dir, topic) LOG.debug("Consumer is a zmq.%s", ['PULL', 'SUB'][sock_type == zmq.SUB]) self.reactor.register(proxy, inaddr, sock_type, subscribe=subscribe, in_bind=False) self.topics.append(topic)
def publisher(waiter): LOG.info(_LI("Creating proxy for topic: %s"), topic) try: # The topic is received over the network, # don't trust this input. if self.badchars.search(topic) is not None: emsg = _("Topic contained dangerous characters.") LOG.warn(emsg) raise RPCException(emsg) out_sock = ZmqSocket("ipc://%s/zmq_topic_%s" % (ipc_dir, topic), sock_type, bind=True) except RPCException: waiter.send_exception(*sys.exc_info()) return self.topic_proxy[topic] = eventlet.queue.LightQueue( CONF.rpc_zmq_topic_backlog) self.sockets.append(out_sock) # It takes some time for a pub socket to open, # before we can have any faith in doing a send() to it. if sock_type == zmq.PUB: eventlet.sleep(.5) waiter.send(True) while(True): data = self.topic_proxy[topic].get() out_sock.send(data, copy=False)
def publisher(waiter): LOG.info(_LI("Creating proxy for topic: %s"), topic) try: # The topic is received over the network, # don't trust this input. if self.badchars.search(topic) is not None: emsg = _("Topic contained dangerous characters.") LOG.warn(emsg) raise RPCException(emsg) out_sock = ZmqSocket("ipc://%s/zmq_topic_%s" % (ipc_dir, topic), sock_type, bind=True) except RPCException: waiter.send_exception(*sys.exc_info()) return self.topic_proxy[topic] = eventlet.queue.LightQueue( CONF.rpc_zmq_topic_backlog) self.sockets.append(out_sock) # It takes some time for a pub socket to open, # before we can have any faith in doing a send() to it. if sock_type == zmq.PUB: eventlet.sleep(.5) waiter.send(True) while (True): data = self.topic_proxy[topic].get() out_sock.send(data, copy=False)
def __init__(self, conf, poller, server): super(RouterConsumer, self).__init__(conf, poller, server, zmq.ROUTER) self.matchmaker = server.matchmaker self.targets = [] self.host = zmq_address.combine_address(self.conf.rpc_zmq_host, self.port) LOG.info(_LI("[%s] Run ROUTER consumer"), self.host)
def __init__(self, driver, conf, matchmaker, target, poller=None): super(ZmqServer, self).__init__() self.driver = driver self.conf = conf self.matchmaker = matchmaker self.target = target self.poller = poller or zmq_async.get_poller() LOG.info( _LI('[%(host)s] Run server %(target)s'), { 'host': self.conf.oslo_messaging_zmq.rpc_zmq_host, 'target': self.target }) self.router_consumer = zmq_router_consumer.RouterConsumer( conf, self.poller, self) \ if not conf.oslo_messaging_zmq.use_router_proxy else None self.dealer_consumer = zmq_dealer_consumer.DealerConsumer( conf, self.poller, self) \ if conf.oslo_messaging_zmq.use_router_proxy else None self.sub_consumer = zmq_sub_consumer.SubConsumer( conf, self.poller, self) \ if conf.oslo_messaging_zmq.use_pub_sub else None self.consumers = [] if self.router_consumer is not None: self.consumers.append(self.router_consumer) if self.dealer_consumer is not None: self.consumers.append(self.dealer_consumer) if self.sub_consumer is not None: self.consumers.append(self.sub_consumer)
def receive_message(self, socket): try: reply_id = socket.recv() empty = socket.recv() assert empty == b'', 'Bad format: empty delimiter expected' request = socket.recv_pyobj() LOG.info( _LI("Received %(msg_type)s message %(msg)s") % { "msg_type": request.msg_type, "msg": str(request.message) }) if request.msg_type == zmq_names.CALL_TYPE: return zmq_incoming_message.ZmqIncomingRequest( self.server, request.context, request.message, socket, reply_id, self.poller) elif request.msg_type in zmq_names.NON_BLOCKING_TYPES: return RouterIncomingMessage(self.server, request.context, request.message, socket, reply_id, request.message_id, self.poller) else: LOG.error(_LE("Unknown message type: %s") % request.msg_type) except zmq.ZMQError as e: LOG.error(_LE("Receiving message failed: %s") % str(e))
def get_single_host(self, target): """Get a single host by target. :param target: the target for messages :type target: Target :returns: a "hostname:port" host """ hosts = self.get_hosts(target) if not hosts: err_msg = "No hosts were found for target %s." % target LOG.error(err_msg) raise oslo_messaging.InvalidTarget(err_msg, target) if len(hosts) == 1: host = hosts[0] LOG.info( _LI("A single host %(host)s found for target %(target)s.") % { "host": host, "target": target }) else: host = random.choice(hosts) LOG.warning( _LW("Multiple hosts %(hosts)s were found for target " " %(target)s. Using the random one - %(host)s.") % { "hosts": hosts, "target": target, "host": host }) return host
def connect_to_address(self, address): if address in self.connections: return stype = zmq_names.socket_type_str(self.socket_type) sid = self.handle.identity try: LOG.info(_LI("Connecting %(stype)s socket %(sid)s to %(address)s"), { "stype": stype, "sid": sid, "address": address }) self.connect(address) except zmq.ZMQError as e: LOG.error( _LE("Failed connecting %(stype)s-%(sid)s to " "%(address)s: %(e)s"), { "stype": stype, "sid": sid, "address": address, "e": e }) raise rpc_common.RPCException( "Failed connecting %(stype)s-%(sid)s to %(address)s: %(e)s" % { "stype": stype, "sid": sid, "address": address, "e": e })
def direct_send(self, msg_id, msg): """Send a 'direct' message.""" timer = rpc_common.DecayingTimer(duration=60) timer.start() # NOTE(sileht): retry at least 60sec, after we have a good change # that the caller is really dead too... while True: try: self.publisher_send(DirectPublisher, msg_id, msg) 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 to reply to %s doesn't " "exist yet, retrying...") % msg_id) time.sleep(1) continue raise return
def _heartbeat_thread_job(self): """Thread that maintains inactive connections """ while not self._heartbeat_exit_event.is_set(): with self._connection_lock.for_heartbeat(): recoverable_errors = ( self.connection.recoverable_channel_errors + self.connection.recoverable_connection_errors) try: try: self._heartbeat_check() # NOTE(sileht): We need to drain event to receive # heartbeat from the broker but don't hold the # connection too much times. In amqpdriver a connection # is used exclusivly for read or for write, so we have # to do this for connection used for write drain_events # already do that for other connection try: self.connection.drain_events(timeout=0.001) except socket.timeout: pass except recoverable_errors as exc: LOG.info(_LI("A recoverable connection/channel error " "occurred, trying to reconnect: %s"), exc) self.ensure_connection() except Exception: LOG.warning(_LW("Unexpected error during heartbeart " "thread processing, retrying...")) LOG.debug('Exception', exc_info=True) self._heartbeat_exit_event.wait( timeout=self._heartbeat_wait_timeout) self._heartbeat_exit_event.clear()
def _complete_shutdown(self): """The AMQP Connection has closed, and the driver shutdown is complete. Clean up controller resources and exit. """ self._socket_connection.close() self.processor.shutdown() LOG.info(_LI("Messaging has shutdown"))
def _update_availability(self): fraction_of_available_instances = 0 for redis_instance in self.matchmaker._redis_instances: if not redis_instance._is_available: is_available = \ self.matchmaker._check_availability(redis_instance) if is_available: LOG.info(_LI("Redis host %s is available again."), redis_instance._address) fraction_of_available_instances += 1 # NOTE(gdavoian): mark an instance as available for # writing to, but wait until all services register # themselves in it for making the instance ready for # reading from redis_instance._is_available = True redis_instance._ready_from = time.time() + \ self.conf.oslo_messaging_zmq.zmq_target_expire else: fraction_of_available_instances += 1 fraction_of_available_instances /= \ float(len(self.matchmaker._redis_instances)) # NOTE(gdavoian): make the sleep time proportional to the number of # currently available instances self._sleep_for = max( self.conf.oslo_messaging_zmq.zmq_target_update * fraction_of_available_instances, self._MIN_SLEEP_FOR)
def send(self, conn, msg, timeout=None): # TODO(sileht): # * use timeout parameter when available # * use rpc_timeout if not instead of hardcoded 60 # * use @retrying timer = rpc_common.DecayingTimer(duration=60) timer.start() while True: try: super(RetryOnMissingExchangePublisher, self).send(conn, msg, timeout) return except conn.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': self.exchange, 'routing_key': self.routing_key}) time.sleep(1) continue raise
def send(self, conn, msg, timeout=None): # TODO(sileht): # * use timeout parameter when available # * use rpc_timeout if not instead of hardcoded 60 # * use @retrying timer = rpc_common.DecayingTimer(duration=60) timer.start() while True: try: super(RetryOnMissingExchangePublisher, self).send(conn, msg, timeout) return except conn.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': self.exchange, 'routing_key': self.routing_key }) time.sleep(1) continue raise
def receive_message(self, socket): try: reply_id = socket.recv() empty = socket.recv() assert empty == b'', 'Bad format: empty delimiter expected' msg_type = socket.recv_string() assert msg_type is not None, 'Bad format: msg type expected' msg_id = None if msg_type != zmq_names.CALL_TYPE: msg_id = socket.recv_string() context = socket.recv_pyobj() message = socket.recv_pyobj() LOG.info(_LI("Received %(msg_type)s message %(msg)s") % {"msg_type": msg_type, "msg": str(message)}) if msg_type == zmq_names.CALL_TYPE: return zmq_incoming_message.ZmqIncomingRequest( self.server, context, message, socket, reply_id, self.poller) elif msg_type in (zmq_names.CAST_TYPES + zmq_names.NOTIFY_TYPES): return RouterIncomingMessage( self.server, context, message, socket, reply_id, msg_id, self.poller) else: LOG.error(_LE("Unknown message type: %s") % msg_type) except zmq.ZMQError as e: LOG.error(_LE("Receiving message failed: %s") % str(e))
def _send_request(self, socket, request): super(PushPublisher, self)._send_request(socket, request) LOG.info(_LI("Publishing message %(message)s to a target %(target)s") % {"message": request.message, "target": request.target})
def direct_send(self, msg_id, msg): """Send a 'direct' message.""" timer = rpc_common.DecayingTimer(duration=60) timer.start() # NOTE(sileht): retry at least 60sec, after we have a good change # that the caller is really dead too... while True: try: self.publisher_send(DirectPublisher, msg_id, msg, error_callback=None) 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 to reply to %s doesn't " "exist yet, retrying...") % msg_id) time.sleep(1) continue self._log_publisher_send_error(msg_id, exc) raise except Exception as exc: self._log_publisher_send_error(msg_id, exc) raise
def _get_single_host(): hosts = self.get_hosts(target) try: if not hosts: err_msg = "No hosts were found for target %s." % target LOG.error(err_msg) raise oslo_messaging.InvalidTarget(err_msg, target) if len(hosts) == 1: host = hosts[0] LOG.info(_LI( "A single host %(host)s found for target %(target)s.") % {"host": host, "target": target}) else: host = random.choice(hosts) LOG.warning(_LW( "Multiple hosts %(hosts)s were found for target " " %(target)s. Using the random one - %(host)s.") % {"hosts": hosts, "target": target, "host": host}) return host except oslo_messaging.InvalidTarget as ex: if timeout: raise oslo_messaging.MessagingTimeout() else: raise ex
def __init__(self, conf, context, matchmaker): self.conf = conf self.context = context self.matchmaker = matchmaker LOG.info(_LI("Running %s proxy") % self.PROXY_TYPE) self.poller = zmq_async.get_poller()
def _send_request(self, socket, request): socket.send(b'', zmq.SNDMORE) socket.send_pyobj(request) LOG.info(_LI("Sending message %(message)s to a target %(target)s") % {"message": request.message, "target": request.target})
def __init__(self, conf, poller, server): super(PullConsumer, self).__init__(conf, poller, server, zmq.PULL) self.matchmaker = server.matchmaker self.host = zmq_address.combine_address(self.conf.rpc_zmq_host, self.port) self.targets = zmq_consumer_base.TargetsManager( conf, self.matchmaker, self.host, zmq.PULL) LOG.info(_LI("[%s] Run PULL consumer"), self.host)
def run(self): try: request = self.queue.get(timeout=self.conf.rpc_poll_timeout) LOG.info(_LI("Redirecting request %s to TCP publisher ...") % request) self.publisher.send_request(request) except six.moves.queue.Empty: return
def listen(self, target): LOG.info(_LI("[%(host)s] Listen to target %(target)s"), {'host': self.host, 'target': target}) self.targets.append(target) self.matchmaker.register(target, self.host, zmq_names.socket_type_str(zmq.ROUTER))
def run(self): request, socket = self.poller.poll(self.conf.rpc_poll_timeout) if request is None: return LOG.info(_LI("Received request and queue it: %s") % str(request)) self.queue.put(request)
def _reply_link_ready(self): """Invoked when the Replies reply link has become active. At this point, we are ready to send/receive messages (via Task processing). """ LOG.info(_LI("Messaging is active (%(hostname)s:%(port)s)"), {'hostname': self.hosts.current.hostname, 'port': self.hosts.current.port}) self._schedule_task_processing()
def __init__(self, conf, poller, server): self.sockets_manager = zmq_publisher_base.SocketsManager( conf, server.matchmaker, zmq.ROUTER, zmq.DEALER) self.host = None super(DealerConsumer, self).__init__(conf, poller, server, zmq.DEALER) self.connection_updater = ConsumerConnectionUpdater( conf, self.matchmaker, self.socket) LOG.info(_LI("[%s] Run DEALER consumer"), self.host)
def put(self, msg_id, message_data): queue = self._queues.get(msg_id) if not queue: LOG.info(_LI('No calling threads waiting for msg_id : %s'), msg_id) LOG.debug(' queues: %(queues)s, message: %(message)s', {'queues': len(self._queues), 'message': message_data}) else: queue.put(message_data)
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
def _call_notify(self, ext, context, message, priority, retry, accepted_drivers): """Emit the notification. """ # accepted_drivers is passed in as a result of the map() function LOG.info(_LI("Routing '%(event)s' notification to '%(driver)s' " "driver"), {'event': message.get('event_type'), 'driver': ext.name}) ext.obj.notify(context, message, priority, retry)
def __init__(self, conf, poller, server): self.reply_sender = zmq_senders.ReplySenderProxy(conf) self.sockets_manager = zmq_sockets_manager.SocketsManager( conf, server.matchmaker, zmq.DEALER) self.host = None super(DealerConsumer, self).__init__(conf, poller, server, zmq.DEALER) self.connection_updater = ConsumerConnectionUpdater( conf, self.matchmaker, self.socket) LOG.info(_LI("[%s] Run DEALER consumer"), self.host)
def put(self, msg_id, message_data): queue = self._queues.get(msg_id) if not queue: LOG.info(_LI("No calling threads waiting for msg_id : %s"), msg_id) LOG.debug( " queues: %(queues)s, message: %(message)s", {"queues": len(self._queues), "message": message_data} ) else: queue.put(message_data)