@Override public ConsulClient getValuesWithOptions(String keyPrefix, BlockingQueryOptions options, Handler<AsyncResult<KeyValueList>> resultHandler) { Query query = Query.of("recurse", true).put(options); request(KV_VALID_CODES, HttpMethod.GET, "/v1/kv/" + urlEncode(keyPrefix), query, null, resultHandler, resp -> { if (resp.statusCode() == HttpResponseStatus.NOT_FOUND.code()) { return new KeyValueList(); } else { List<KeyValue> list = resp.bodyAsJsonArray().stream().map(obj -> KVParser.parse((JsonObject) obj)).collect(Collectors.toList()); return new KeyValueList().setList(list).setIndex(Long.parseLong(resp.headers().get(INDEX_HEADER))); } }); return this; }
@Override public void get(Handler<AsyncResult<Buffer>> completionHandler) { client.getValues(prefix, kv -> { if (kv.succeeded()) { KeyValueList list = kv.result(); if (list.isPresent()) { JsonObject tree = getTree(list, prefix.length(), delimiter); completionHandler.handle(Future.succeededFuture(Buffer.buffer(tree.toString()))); } else { completionHandler.handle(Future.succeededFuture(Buffer.buffer("{}"))); } } else { completionHandler.handle(Future.failedFuture(kv.cause())); } }); }
public static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, KeyValueList obj) { for (java.util.Map.Entry<String, Object> member : json) { switch (member.getKey()) { case "index": if (member.getValue() instanceof Number) { obj.setIndex(((Number)member.getValue()).longValue()); } break; case "list": if (member.getValue() instanceof JsonArray) { java.util.ArrayList<io.vertx.ext.consul.KeyValue> list = new java.util.ArrayList<>(); ((Iterable<Object>)member.getValue()).forEach( item -> { if (item instanceof JsonObject) list.add(new io.vertx.ext.consul.KeyValue((JsonObject)item)); }); obj.setList(list); } break; } } }
@Test public void testKeyValueListCopy() { List<KeyValue> list = new ArrayList<>(); list.add(randomKeyValue()); list.add(randomKeyValue()); KeyValueList kvList = new KeyValueList() .setList(list) .setIndex(randomLong()); checkKeyValueList(kvList, new KeyValueList(kvList)); checkKeyValueList(kvList, new KeyValueList(kvList.toJson())); List<KeyValue> shuffled = new ArrayList<>(); shuffled.add(list.get(1)); shuffled.add(list.get(0)); KeyValueList kvShuffled = new KeyValueList() .setList(shuffled) .setIndex(kvList.getIndex()); checkKeyValueList(kvList, kvShuffled); }
private void checkKeyValueList(KeyValueList expected, KeyValueList actual) { assertEquals(expected, actual); assertEquals(expected.hashCode(), actual.hashCode()); assertEquals(expected.getIndex(), actual.getIndex()); List<KeyValue> expectedList = expected.getList(); List<KeyValue> actualList = actual.getList(); assertTrue(expectedList.containsAll(actualList)); assertTrue(actualList.containsAll(expectedList)); }
@Test public void testKeyPrefix() throws InterruptedException { StateConsumer<String> consumer = new StateConsumer<>(); String keyPrefix = ConsulContext.KEY_RW_PREFIX + randomAlphaString(10); String k1 = keyPrefix + randomAlphaString(10); String k2 = keyPrefix + randomAlphaString(10); String v1 = randomAlphaString(10); String v2 = randomAlphaString(10); assertTrue(getAsync(h -> ctx.writeClient().putValue(k1, v1, h))); Watch<KeyValueList> watch = Watch.keyPrefix(keyPrefix, vertx, ctx.readClientOptions()) .setHandler(kv -> { if (kv.succeeded()) { if (kv.nextResult().isPresent()) { consumer.consume(kv.nextResult().getList().stream().map(KeyValue::getValue).sorted().collect(Collectors.joining("/"))); } else { consumer.consume(EMPTY_MESSAGE); } } else { consumer.consume(kv.cause().getMessage()); } }) .start(); consumer.await(v1); assertTrue(getAsync(h -> ctx.writeClient().putValue(k2, v2, h))); consumer.await(Stream.of(v1, v2).sorted().collect(Collectors.joining("/"))); runAsync(h -> ctx.writeClient().deleteValues(keyPrefix, h)); consumer.await(EMPTY_MESSAGE); consumer.check(); watch.stop(); }
private static JsonObject getTree(KeyValueList list, int prefix, String delimiter) { JsonObject tree = new JsonObject(); for (KeyValue keyValue : list.getList()) { if (keyValue.getKey().endsWith(delimiter)) { continue; } JsonObject json = tree; String[] arr = keyValue.getKey().substring(prefix).split(delimiter); for (int i = 0; i < arr.length; i++) { String key = arr[i]; if (i == arr.length - 1) { json.put(key, keyValue.getValue()); } else { JsonObject next = json.getJsonObject(key); if (next == null) { next = new JsonObject(); json.put(key, next); } json = next; } } } return tree; }
@Override void wait(long index, Handler<AsyncResult<State<KeyValueList>>> handler) { BlockingQueryOptions options = new BlockingQueryOptions().setWait(BLOCKING_WAIT).setIndex(index); consulClient.getValuesWithOptions(keyPrefix, options, h -> handler.handle(h.map(kv -> new State<KeyValueList>(kv, kv.getIndex())))); } }
@Override public int hashCode() { int result = (int) (index ^ (index >>> 32)); result = 31 * result + (list != null ? sorted().hashCode() : 0); return result; }
private void getEntries(TestContext tc, String prefix, Handler<List<String>> resultHandler) { ctx.readClient().getValues(prefix, tc.asyncAssertSuccess(list -> { resultHandler.handle(list.getList().stream() .map(kv -> kv.getKey() + "/" + kv.getValue()).collect(Collectors.toList())); })); }
@Test public void canGetValuesBlocking(TestContext tc) { blockingQuery(tc, (key, h) -> ctx.readClient().getValues(key, tc.asyncAssertSuccess(list -> h.handle(list.getIndex())))); }
private void blockingQuery(TestContext tc, BiConsumer<String, Handler<Long>> indexSupplier) { String key = randomFooBarAlpha(); String value = randomAlphaString(10); ctx.writeClient() .putValue(key, randomAlphaString(10), tc.asyncAssertSuccess(b1 -> { tc.assertTrue(b1); indexSupplier.accept(key, consulIndex -> { Async async = tc.async(2); vertx.setTimer(TimeUnit.SECONDS.toMillis(2), l -> { ctx.writeClient().putValue(key, value, tc.asyncAssertSuccess(b2 -> { tc.assertTrue(b2); ctx.readClient().getValueWithOptions(key, new BlockingQueryOptions().setIndex(consulIndex), tc.asyncAssertSuccess(kv -> { tc.assertTrue(kv.getModifyIndex() > consulIndex); tc.assertEquals(kv.getValue(), value); async.countDown(); })); ctx.readClient().getValuesWithOptions("foo/bar", new BlockingQueryOptions().setIndex(consulIndex), tc.asyncAssertSuccess(kv -> { tc.assertTrue(kv.getIndex() > consulIndex); tc.assertTrue(kv.getList().size() == 1); async.countDown(); })); })); }); async.handler(v -> ctx.writeClient().deleteValue(key, tc.asyncAssertSuccess())); }); })); } }
private void valuesAccess(TestContext tc, ConsulClient accessClient) { String key1 = randomFooBarAlpha(); String value1 = randomAlphaString(10); String key2 = randomFooBarAlpha(); String value2 = randomAlphaString(10); ctx.writeClient().putValue(key1, value1, tc.asyncAssertSuccess(b1 -> { tc.assertTrue(b1); ctx.writeClient().putValue(key2, value2, tc.asyncAssertSuccess(b2 -> { tc.assertTrue(b2); accessClient.getValues("foo/bar", tc.asyncAssertSuccess(kvList -> { List<KeyValue> list = kvList.getList(); tc.assertEquals(list.size(), 2); tc.assertTrue(list.stream() .filter(kv -> kv.getKey().equals(key1) && kv.getValue().equals(value1)) .count() == 1); tc.assertTrue(list.stream() .filter(kv -> kv.getKey().equals(key2) && kv.getValue().equals(value2)) .count() == 1); ctx.writeClient().deleteValues("foo/bar", tc.asyncAssertSuccess()); })); })); })); }
@Test public void keysNotFound(TestContext tc) { String key = randomFooBarUnicode(); ctx.readClient() .getValues(key, tc.asyncAssertSuccess(list -> { tc.assertFalse(list.isPresent()); })); }