Source:
protected <K, V> Map<K, V> loadDataAsync(final Collection<K> keys, final Function<K, String> keyConverter, final BiFunction<K, byte[], V> valueConverter) throws ServiceTemporarilyUnavailableException, NakadiRuntimeException { final Map<K, V> result = new HashMap<>(); final CountDownLatch latch = new CountDownLatch(keys.size()); try { for (final K key : keys) { final String zkKey = keyConverter.apply(key); getCurator().getData().inBackground((client, event) -> { try { if (event.getResultCode() == KeeperException.Code.OK.intValue()) { final V value = valueConverter.apply(key, event.getData()); synchronized (result) { result.put(key, value); } } else { getLog().error( "Failed to get data from zk. status code: {}", zkKey, event.getResultCode()); } } catch (RuntimeException ex) { getLog().error("Failed to memorize key value", key, ex); } finally { latch.countDown(); } }).forPath(zkKey); } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); throw new ServiceTemporarilyUnavailableException("Failed to wait for zk response", ex); } catch (Exception ex) { throw new NakadiRuntimeException(ex); } try { if (!latch.await(MAX_ZK_RESPONSE_SECONDS, TimeUnit.SECONDS)) { throw new ServiceTemporarilyUnavailableException("Failed to wait for zk response", null); } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); throw new ServiceTemporarilyUnavailableException("Failed to wait for zk response", ex); } if (result.size() != keys.size()) { throw new ServiceTemporarilyUnavailableException("Failed to wait for keys " + keys.stream() .filter(v -> !result.containsKey(v)) .map(String::valueOf) .collect(Collectors.joining(", ")) + " to be in response", null); } return result; }

Target:
protected <K, V> Map<K, V> loadDataAsync(final Collection<K> keys, final Function<K, String> keyConverter, final BiFunction<K, byte[], V> valueConverter) throws ServiceTemporarilyUnavailableException, NakadiRuntimeException { final Map<K, V> result = new HashMap<>(); final CountDownLatch latch = new CountDownLatch(keys.size()); try { for (final K key : keys) { final String zkKey = keyConverter.apply(key); getCurator().getData().inBackground((client, event) -> { try { if (event.getResultCode() == KeeperException.Code.OK.intValue()) { final V value = valueConverter.apply(key, event.getData()); synchronized (result) { result.put(key, value); } } else { getLog().error( "Failed to get data from zk. status code: {}", zkKey, event.getResultCode()); } } catch (RuntimeException ex) { getLog().error("Failed to memorize key value", key, ex); } finally { latch.countDown(); } }).forPath(zkKey); } } catch (Exception ex) { throw new NakadiRuntimeException(ex); } try { if (!latch.await(MAX_ZK_RESPONSE_SECONDS, TimeUnit.SECONDS)) { throw new ServiceTemporarilyUnavailableException("Failed to wait for zk response", null); } } catch (InterruptedException ex) { Thread.currentThread().interrupt(); throw new ServiceTemporarilyUnavailableException("Failed to wait for zk response", ex); } if (result.size() != keys.size()) { throw new ServiceTemporarilyUnavailableException("Failed to wait for keys " + keys.stream() .filter(v -> !result.containsKey(v)) .map(String::valueOf) .collect(Collectors.joining(", ")) + " to be in response", null); } return result; }