/** * Retrieves a {@link com.orbitz.consul.model.ConsulResponse} with the * {@link com.orbitz.consul.model.kv.Value} for a spefici key from the * key/value store * @param key The key to retrieve * @return An {@link Optional} containing the {@link ConsulResponse} or {@link Optional#empty()()} */ public Optional<ConsulResponse<Value>> getConsulResponseWithValue(String key) { return getConsulResponseWithValue(key, QueryOptions.BLANK); }
private void removeResponseFromEndpointDocument(ObjectMapper mapper, JsonNode id) throws IOException { final ConsulResponse<Value> initialEndpointValue = kv.getConsulResponseWithValue(endpointKey).orElse(null); if (initialEndpointValue == null) { return; } ConsulHelper.atomicUpdate(kv, initialEndpointValue, value -> { try { if (Strings.isNullOrEmpty(value)) { return value; } EndpointDocument doc = mapper.readValue(value, EndpointDocument.class); doc.removeResponse(id); return mapper.writeValueAsString(doc); } catch (IOException e) { LOGGER.error("Failed to remove response with ID {} from malformed RPC endpoint document,", e); return value; } }); }
public static ConsulResponse<Value> getWithRetry(KeyValueClient kv, String key, BackoffPolicy backoffPolicy) throws TimeoutException { final Iterator<TimeValue> retryDelays = backoffPolicy.iterator(); while (true) { final ConsulResponse<Value> response = kv.getConsulResponseWithValue(key).orElse(null); if (response != null) { return response; } try { if (!retryDelays.hasNext()) { break; } final TimeValue retryDelay = retryDelays.next(); LOGGER.debug("Document does not exist; sleeping for {} and then trying again to get {}", retryDelay, key); retryDelay.timeUnit().sleep(retryDelay.duration()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } throw new TimeoutException("getWithRetry timed out for key " + key); }
private void bind() throws InterruptedException, EndpointAlreadyInUseException { while (!closed()) { LOGGER.info("Attempting to binding to RPC endpoint document {}", endpointKey); final boolean acquired = kv.acquireLock(endpointKey, "{}", sessionId); if (acquired) { LOGGER.info("Successfully bound to RPC endpoint document {}", endpointKey); return; } final Optional<ConsulResponse<Value>> existing = kv.getConsulResponseWithValue(endpointKey); if (existing.isPresent()) { // somebody else has acquired the lock final String lockSession = existing.get().getResponse().getSession().orElse(null); throw new EndpointAlreadyInUseException( "Failed to lock RPC endpoint document " + endpointKey + " ; already locked by session " + lockSession); } LOGGER.info("Endpoint lock acquisition failed; will retry after delay."); SECONDS.sleep(1); } } }
public static ConsulResponse<Value> awaitChange(KeyValueClient kv, String key, BigInteger index) { while (true) { final ConsulResponse<Value> response = kv.getConsulResponseWithValue(key, ImmutableQueryOptions.builder() .index(index) .wait("5m") .build()) .orElse(null); if (response == null) { LOGGER.debug("Document does not exist: {}", key); return null; } if (index.equals(response.getIndex())) { LOGGER.debug("Long poll timed out, polling again for {}", key); } else { return response; } } }
private static void atomicUpdate(KeyValueClient kv, String key, Function<String, String> mutator) throws IOException { while (true) { final ConsulResponse<Value> r = kv.getConsulResponseWithValue(key).orElse(null); if (r == null) { // Don't automatically create the document, because it might need to be associated with another node's session. // For example, an RPC endpoint doc is updated by both client and server, but is tied to the server session. throw new IOException("Can't update non-existent document: " + key); } final BigInteger index = r.getIndex(); final String oldValue = r.getResponse().getValueAsString(UTF_8).orElse(missingDocumentValue); final String newValue = mutator.apply(oldValue); if (Objects.equals(newValue, oldValue)) { return; } final PutOptions options = ImmutablePutOptions.builder().cas(index.longValue()).build(); boolean success = kv.putValue(key, newValue, 0, options, UTF_8); if (success) { return; } // todo truncated exponential backoff, please! Die if timeout! //MILLISECONDS.sleep(100); } }
final long waitSeconds = Math.min(300, timeoutEnforcer.remaining(SECONDS)); final ConsulResponse<Value> response = kv.getConsulResponseWithValue(key, ImmutableQueryOptions.builder() .index(index)
public static void awaitRemoval(KeyValueClient kv, String key) { BigInteger index = BigInteger.ZERO; while (true) { final ConsulResponse<Value> response = kv.getConsulResponseWithValue(key, ImmutableQueryOptions.builder() .index(index) .wait("5m") .build()) .orElse(null); if (response == null) { return; } index = response.getIndex(); } }