use of com.couchbase.connector.cluster.consul.rpc.RpcEndpoint in project couchbase-elasticsearch-connector by couchbase.
the class LeaderTask method rebalance.
private void rebalance() throws InterruptedException {
final String configLocation = ctx.keys().config();
LOGGER.info("Reading connector config from Consul key: {}", configLocation);
final String config = ctx.consul().keyValueClient().getValue(configLocation).orElseThrow(() -> new ConfigException("missing Consul config key: " + configLocation)).getValueAsString(UTF_8).orElseThrow(() -> new ConfigException("missing value for Consul key: " + configLocation));
// Sanity check, validate the config.
ConnectorConfig.from(config);
restartRebalance: while (true) {
LOGGER.info("Rebalancing the cluster");
// dumb strategy: shut everything down, then reassign vbuckets
stopStreaming();
final List<RpcEndpoint> endpoints = awaitReadyEndpoints();
for (int i = 0; i < endpoints.size(); i++) {
throwIfDone();
final int memberNumber = i + 1;
final int clusterSize = endpoints.size();
final Membership membership = Membership.of(memberNumber, clusterSize);
final RpcEndpoint endpoint = endpoints.get(i);
LOGGER.info("Assigning group membership {} to endpoint {}", membership, endpoint);
try {
endpoint.service(WorkerService.class).startStreaming(membership, config);
} catch (Throwable t) {
// todo what happens here? What if it fails due to timeout, and the worker is actually doing the work?
// For now, start the whole rebalance process over again. This is obviously not ideal.
LOGGER.warn("Failed to assign group membership {} to endpoint {}", membership, endpoint, t);
SECONDS.sleep(3);
continue restartRebalance;
}
}
// success!
return;
}
}
use of com.couchbase.connector.cluster.consul.rpc.RpcEndpoint in project couchbase-elasticsearch-connector by couchbase.
the class DocumentKeys method waitForClusterToQuiesce.
private void waitForClusterToQuiesce(Duration timeout) throws TimeoutException {
final TimeoutEnforcer timeoutEnforcer = new TimeoutEnforcer(timeout);
try (Broadcaster broadcaster = new Broadcaster()) {
while (true) {
final List<RpcEndpoint> allEndpoints = listRpcEndpoints();
final Map<RpcEndpoint, RpcResult<Boolean>> results = broadcaster.broadcast("stopped?", allEndpoints, WorkerService.class, WorkerService::stopped);
boolean stopped = true;
for (Map.Entry<RpcEndpoint, RpcResult<Boolean>> e : results.entrySet()) {
if (e.getValue().isFailed()) {
LOGGER.warn("Status request failed for endpoint " + e.getKey());
stopped = false;
} else if (!e.getValue().get()) {
LOGGER.warn("Endpoint is still working: " + e.getKey());
stopped = false;
}
}
if (stopped) {
return;
}
timeoutEnforcer.throwIfExpired();
LOGGER.info("Retrying in just a moment...");
SECONDS.sleep(2);
}
} catch (Exception e) {
throwIfUnchecked(e);
propagateIfPossible(e, TimeoutException.class);
throw new RuntimeException(e);
}
}
use of com.couchbase.connector.cluster.consul.rpc.RpcEndpoint in project couchbase-elasticsearch-connector by couchbase.
the class LeaderTask method stopStreaming.
private void stopStreaming() throws InterruptedException {
int attempt = 1;
// Repeat until all endpoints successfully acknowledge they have been shut down
while (true) {
throwIfDone();
final List<RpcEndpoint> endpoints = ctx.keys().listRpcEndpoints(Duration.ofSeconds(15));
final Map<RpcEndpoint, RpcResult<Void>> stopResults = broadcaster.broadcast("stop", endpoints, WorkerService.class, WorkerService::stopStreaming);
if (stopResults.entrySet().stream().noneMatch(e -> e.getValue().isFailed())) {
if (attempt != 1) {
LOGGER.warn("Multiple attempts were required to quiesce the cluster. Sleeping for an additional {} to allow unreachable nodes to terminate.", quietPeriodAfterFailedShutdownRequest);
sleep(quietPeriodAfterFailedShutdownRequest);
}
LOGGER.info("Cluster quiesced.");
return;
}
LOGGER.warn("Attempt #{} to quiesce the cluster failed. Will retry.", attempt);
attempt++;
SECONDS.sleep(5);
}
}
use of com.couchbase.connector.cluster.consul.rpc.RpcEndpoint in project couchbase-elasticsearch-connector by couchbase.
the class RpcSandbox method main.
public static void main(String[] args) {
final ConsulContext ctx = new ConsulContext(Consul.builder(), SERVICE_NAME, null);
// final List<ServiceHealth> healthyServices = consul.healthClient().getHealthyServiceInstances(Sandbox.serviceName).getResponse();
final Duration defaultTimeout = Duration.ofSeconds(30);
// for (ServiceHealth serviceHealth : healthyServices) {
// final String endpointId = String.join("::",
// serviceHealth.getNode().getNode(),
// serviceHealth.getNode().getAddress(),
// serviceHealth.getService().getId());
// final String endpointKey = rpcEndpointKey(Sandbox.serviceName, endpointId);
final DocumentKeys keys = ctx.keys();
for (RpcEndpoint endpoint : keys.listRpcEndpoints(defaultTimeout)) {
System.out.println(endpoint);
final WorkerService follower = endpoint.service(WorkerService.class);
System.out.println(follower.metrics());
follower.ping();
follower.sleep(3);
//
// System.out.println("Before sleep 3");
// follower.sleep(3);
// System.out.println("After sleep 3");
//
// System.out.println("Before sleep 16");
//
// try {
// endpoint.withTimeout(Duration.ofSeconds(1))
// .service(FollowerService.class)
// .sleep(16);
// } catch (Exception e) {
// e.printStackTrace();
// }
// //
// System.out.println("After sleep 16");
}
System.out.println("done");
// final Member member = consul.agentClient().getAgent().getMember();
// final String endpointId = String.join("::", member.getName(), member.getAddress(), serviceId);
//
//
// JsonRpcHttpClient client = new ConsulRpcClient(consul.keyValueClient(), )(objectMapper, jsonRpcRequest) -> {
// System.out.println("Here in executor, request = " + jsonRpcRequest);
// return mapper.createObjectNode().put("result", "Hello world");
// };
// ServiceFactory factory = new ServiceFactory(mapper, client);
// GreetingService service = factory.createService(GreetingService.class);
//
// System.out.println(service.greet("Harold"));
}
Aggregations