class ShardInfoDownloader {

    public Map<String, ShardingInfo> getShardInfoFromPeers() {
        log.debug(">> Requesting ShardingInfo from Peers...");
        int counterTotal = 0;

        Set<Peer> kp = peers.getAllConnectedPeers();
        Set<String> knownPeers = new HashSet<>();
        kp.forEach((p) -> {
            knownPeers.add(p.getHostWithPort());
        });
        log.debug("Get ShardInfo from knownPeers [{}]...", knownPeers.size());
        //get sharding info from known peers
        for (String pa : randomizeOrder(knownPeers)) {
            ShardingInfo si = getShardingInfoFromPeer(pa);
            //do not count peers that do not create shrds
            if (si != null && !si.isShardingOff) {
                shardInfoByPeers.put(pa, si);
                additionalPeers.addAll(si.knownPeers);
            }
            if (shardInfoByPeers.size() >= ENOUGH_PEERS_FOR_SHARD_INFO) {
                log.debug("counter >= ENOUGH_PEERS_FOR_SHARD_INFO {}", true);
                break;
            }
            counterTotal++;
            if (counterTotal >= ENOUGH_PEERS_FOR_SHARD_INFO_TOTAL) {
                break;
            }
        }
        //we have not enough known peers, connect to additional
        if (shardInfoByPeers.size() < ENOUGH_PEERS_FOR_SHARD_INFO) {
            //we need new ones only here
            additionalPeers.removeAll(knownPeers);
            log.debug("Get ShardInfo from additionalPeers [{}]...", additionalPeers.size());
            for (String pa : randomizeOrder(additionalPeers)) {
                ShardingInfo si = getShardingInfoFromPeer(pa);
                if (si != null && !si.isShardingOff) {
                    shardInfoByPeers.put(pa, si);
                } else {
                    log.warn("No shardInfo '{}' from peerAddress = {}", si, pa);
                }
                if (shardInfoByPeers.size() > ENOUGH_PEERS_FOR_SHARD_INFO) {
                    log.debug("counter > ENOUGH_PEERS_FOR_SHARD_INFO {}", true);
                    break;
                }
                counterTotal++;
                if (counterTotal > ENOUGH_PEERS_FOR_SHARD_INFO_TOTAL) {
                    break;
                }
            }
        }
        log.debug("<< Found shardInfoByPeers [{}]", shardInfoByPeers.size());
        log.trace("<< shardInfoByPeers {}", shardInfoByPeers);
        return shardInfoByPeers;
    }

    @Inject public  ShardInfoDownloader(PeersService peers);

}