def _maybe_refresh_metadata(self, wakeup=False):
        """Send a metadata request if needed.

        Returns:
            int: milliseconds until next refresh
        """
        ttl = self.cluster.ttl()
        wait_for_in_progress_ms = self.config['request_timeout_ms'] if self._metadata_refresh_in_progress else 0
        metadata_timeout = max(ttl, wait_for_in_progress_ms)

        if metadata_timeout > 0:
            return metadata_timeout

        # Beware that the behavior of this method and the computation of
        # timeouts for poll() are highly dependent on the behavior of
        # least_loaded_node()
        node_id = self.least_loaded_node()
        if node_id is None:
            log.debug("Give up sending metadata request since no node is available");
            return self.config['reconnect_backoff_ms']

        if self._can_send_request(node_id):
            topics = list(self._topics)
            if not topics and self.cluster.is_bootstrap(node_id):
                topics = list(self.config['bootstrap_topics_filter'])

            if self.cluster.need_all_topic_metadata or not topics:
                topics = [] if self.config['api_version'] < (0, 10) else None
            api_version = 0 if self.config['api_version'] < (0, 10) else 1
            request = MetadataRequest[api_version](topics)
            log.debug("Sending metadata request %s to node %s", request, node_id)
            future = self.send(node_id, request, wakeup=wakeup)
            future.add_callback(self.cluster.update_metadata)
            future.add_errback(self.cluster.failed_update)

            self._metadata_refresh_in_progress = True
            def refresh_done(val_or_error):
                self._metadata_refresh_in_progress = False
            future.add_callback(refresh_done)
            future.add_errback(refresh_done)
            return self.config['request_timeout_ms']

        # If there's any connection establishment underway, wait until it completes. This prevents
        # the client from unnecessarily connecting to additional nodes while a previous connection
        # attempt has not been completed.
        if self._connecting:
            return self.config['reconnect_backoff_ms']

        if self.maybe_connect(node_id, wakeup=wakeup):
            log.debug("Initializing connection to node %s for metadata request", node_id)
            return self.config['reconnect_backoff_ms']

        # connected but can't send more, OR connecting
        # In either case we just need to wait for a network event
        # to let us know the selected connection might be usable again.
        return float('inf')
Send a metadata request if needed.

        Returns:
            int: milliseconds until next refresh