protected void queryClusterNodes(Collection<ClickHouseNode> seeds, Collection<ClickHouseNode> allNodes,
            Collection<ClickHouseNode> newHealthyNodes, Collection<ClickHouseNode> newFaultyNodes,
            Collection<ClickHouseNode> useless) {
        for (ClickHouseNode node : seeds) {
            ClickHouseNode server = null;
            try {
                server = node.probe();
            } catch (Exception e) {
                // ignore
            }
            if (server == null) {
                newFaultyNodes.add(node);
                continue;
            } else if (!server.equals(node)) {
                allNodes.add(server);
                useless.add(node);
            }

            try (ClickHouseClient client = ClickHouseClient.builder().agent(false)
                    .nodeSelector(ClickHouseNodeSelector.of(server.getProtocol())).build()) {
                ClickHouseRequest<?> request = client.read(server)
                        .format(ClickHouseFormat.RowBinaryWithNamesAndTypes);
                String clusterName = server.getCluster();
                Set<String> clusters = new LinkedHashSet<>();
                if (!ClickHouseChecker.isNullOrEmpty(clusterName)) {
                    clusters.add(clusterName);
                }
                boolean isAddress = true;
                boolean proceed = false;
                try (ClickHouseResponse response = request
                        .query(clusters.isEmpty() ? policy.getQueryForAllLocalNodes()
                                : policy.getQueryForClusterLocalNodes())
                        .params(ClickHouseValues.convertToQuotedString(clusterName))
                        .executeAndWait()) {
                    for (ClickHouseRecord r : response.records()) {
                        int idx = 0;
                        String cluster = r.getValue(idx++).asString();
                        clusters.add(cluster);
                        String addr = r.getValue(idx++).asString();
                        String name = r.getValue(idx++).asString();
                        if (!(isAddress = server.getHost().equals(addr)) && !server.getHost().equals(name)) {
                            log.warn(
                                    "Auto discovery may not work as no host_name and host_address in system.clusters matched with %s",
                                    server);
                            isAddress = true; // fall back to host_address
                        }
                        ClickHouseNode discovered = ClickHouseNode.builder(server).cluster(cluster)
                                .replica(r.getValue(idx++).asInteger())
                                .shard(r.getValue(idx++).asInteger(), r.getValue(idx++).asInteger()).build();
                        if (!discovered.equals(server)) {
                            allNodes.remove(server);
                            allNodes.add(discovered);
                            newHealthyNodes.add(discovered);
                            useless.add(server);
                        }
                        proceed = true;
                    }
                } catch (Exception e) {
                    log.warn("Failed to query system.clusters using %s, due to: %s", server, e.getMessage());
                    if (e.getCause() instanceof IOException) {
                        useless.add(server);
                        continue;
                    }
                }

                if (!proceed) {
                    continue;
                }

                String query = policy.getQueryForNonLocalNodes();
                int limit = template.config.getIntOption(ClickHouseClientOption.NODE_DISCOVERY_LIMIT);
                if (limit > 0) {
                    query = query + " limit " + limit;
                }
                try (ClickHouseResponse response = request.query(query)
                        .params(isAddress ? "host_address" : "host_name",
                                ClickHouseValues.convertToSqlExpression(clusters))
                        .executeAndWait()) {
                    for (ClickHouseRecord r : response.records()) {
                        int idx = 0;
                        ClickHouseNode n = ClickHouseNode.builder(server).cluster(r.getValue(idx++).asString())
                                .addOption(ClickHouseClientOption.AUTO_DISCOVERY.getKey(), "false")
                                .host(r.getValue(idx++).asString()).replica(r.getValue(idx++).asInteger())
                                .shard(r.getValue(idx++).asInteger(), r.getValue(idx++).asInteger()).build();
                        allNodes.add(n);
                        // we have seed nodes so here we can be more defensive
                        newFaultyNodes.add(n);
                    }
                } catch (Exception e) {
                    log.warn("Failed to query system.clusters using %s", server, e);
                    newHealthyNodes.remove(server);
                    newFaultyNodes.add(server);
                }
            }
        }
    }
Default constructor.

@param nodes    non-empty list of nodes
@param template non-null template node
clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseNodes.java