use of com.couchbase.client.core.config.BucketConfig in project couchbase-jvm-clients by couchbase.
the class Observe method poll.
public static Mono<Void> poll(final ObserveContext ctx) {
if (ctx.persistTo() == ObservePersistTo.NONE && ctx.replicateTo() == ObserveReplicateTo.NONE) {
return Mono.empty();
}
if (!ctx.environment().ioConfig().mutationTokensEnabled() || !ctx.mutationToken().isPresent()) {
return Mono.error(new FeatureNotAvailableException("To use PersistTo and/or ReplicateTo, mutation tokens must " + "be enabled on the IO configuration"));
}
final RequestSpan parentSpan = ctx.environment().requestTracer().requestSpan("observe", ctx.parentSpan());
Flux<ObserveItem> observed = Flux.defer(() -> {
BucketConfig config = ctx.core().clusterConfig().bucketConfig(ctx.collectionIdentifier().bucket());
return Flux.just(validateReplicas(config, ctx.persistTo(), ctx.replicateTo()));
}).flatMap(replicas -> viaMutationToken(replicas, ctx, parentSpan));
return maybeRetry(observed, ctx).timeout(ctx.timeout(), ctx.environment().scheduler()).doFinally(t -> parentSpan.end());
}
use of com.couchbase.client.core.config.BucketConfig in project couchbase-jvm-clients by couchbase.
the class KeyValueLocator method dispatch.
@Override
public void dispatch(final Request<? extends Response> request, final List<Node> nodes, final ClusterConfig config, final CoreContext ctx) {
if (request.target() != null) {
dispatchTargeted(request, nodes, ctx);
} else {
KeyValueRequest r = (KeyValueRequest) request;
String bucket = r.bucket();
BucketConfig bucketConfig = config.bucketConfig(bucket);
if (bucketConfig == null) {
// Since a bucket is opened lazily, it might not be available yet (or for some
// other reason the config is gone) - send it into retry!
RetryOrchestrator.maybeRetry(ctx, request, ctx.core().configurationProvider().bucketConfigLoadInProgress() ? RetryReason.BUCKET_OPEN_IN_PROGRESS : RetryReason.BUCKET_NOT_AVAILABLE);
return;
}
if (bucketConfig instanceof CouchbaseBucketConfig) {
couchbaseBucket(r, nodes, (CouchbaseBucketConfig) bucketConfig, ctx);
} else if (bucketConfig instanceof MemcachedBucketConfig) {
memcacheBucket(r, nodes, (MemcachedBucketConfig) bucketConfig, ctx);
} else {
throw new IllegalStateException("Unsupported Bucket Type: " + bucketConfig + " for request " + request);
}
}
}
use of com.couchbase.client.core.config.BucketConfig in project couchbase-jvm-clients by couchbase.
the class BaseBucketLoaderTest method loadsAndParsesConfig.
@Test
void loadsAndParsesConfig() {
BucketLoader loader = new BaseBucketLoader(core, SERVICE) {
@Override
protected Mono<byte[]> discoverConfig(NodeIdentifier seed, String bucket) {
return Mono.just(readResource("../config_with_external.json", BaseBucketLoaderTest.class).getBytes(UTF_8));
}
};
when(core.ensureServiceAt(eq(SEED), eq(SERVICE), eq(PORT), eq(Optional.of(BUCKET)), eq(Optional.empty()))).thenReturn(Mono.empty());
when(core.serviceState(eq(SEED), eq(SERVICE), eq(Optional.of(BUCKET)))).thenReturn(Optional.of(Flux.empty()));
ProposedBucketConfigContext ctx = loader.load(SEED, PORT, BUCKET, Optional.empty()).block();
BucketConfig config = BucketConfigParser.parse(ctx.config(), core.context().environment(), ctx.origin());
assertEquals("default", config.name());
assertEquals(1073, config.rev());
}
use of com.couchbase.client.core.config.BucketConfig in project couchbase-jvm-clients by couchbase.
the class WaitUntilReadyHelper method waitUntilReady.
@Stability.Internal
public static CompletableFuture<Void> waitUntilReady(final Core core, final Set<ServiceType> serviceTypes, final Duration timeout, final ClusterState desiredState, final Optional<String> bucketName) {
final WaitUntilReadyState state = new WaitUntilReadyState();
state.transition(WaitUntilReadyStage.CONFIG_LOAD);
return Flux.interval(Duration.ofMillis(10), core.context().environment().scheduler()).onBackpressureDrop().filter(i -> !(core.configurationProvider().bucketConfigLoadInProgress() || core.configurationProvider().globalConfigLoadInProgress() || (bucketName.isPresent() && core.configurationProvider().collectionRefreshInProgress()) || (bucketName.isPresent() && core.clusterConfig().bucketConfig(bucketName.get()) == null))).filter(i -> {
// created.
if (bucketName.isPresent()) {
state.transition(WaitUntilReadyStage.BUCKET_CONFIG_READY);
BucketConfig bucketConfig = core.clusterConfig().bucketConfig(bucketName.get());
long extNodes = bucketConfig.portInfos().stream().filter(p -> p.ports().containsKey(ServiceType.KV)).count();
long visibleNodes = bucketConfig.nodes().stream().filter(n -> n.services().containsKey(ServiceType.KV)).count();
return extNodes > 0 && extNodes == visibleNodes;
} else {
return true;
}
}).flatMap(i -> {
if (bucketName.isPresent()) {
state.transition(WaitUntilReadyStage.BUCKET_NODES_HEALTHY);
// To avoid tmpfails on the bucket, we double check that all nodes from the nodes list are
// in a healthy status - but for this we need to actually fetch the verbose config, since
// the terse one doesn't have that status in it.
GenericManagerRequest request = new GenericManagerRequest(core.context(), () -> new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/pools/default/buckets/" + bucketName.get()), true, null);
core.send(request);
return Reactor.wrap(request, request.response(), true).filter(response -> {
if (response.status() != ResponseStatus.SUCCESS) {
return false;
}
ObjectNode root = (ObjectNode) Mapper.decodeIntoTree(response.content());
ArrayNode nodes = (ArrayNode) root.get("nodes");
long healthy = StreamSupport.stream(nodes.spliterator(), false).filter(node -> node.get("status").asText().equals("healthy")).count();
return nodes.size() == healthy;
}).map(ignored -> i);
} else {
return Flux.just(i);
}
}).take(1).flatMap(aLong -> {
// to being ready at this point. Bucket level wait until ready is the way to go there.
if (!bucketName.isPresent() && !core.clusterConfig().hasClusterOrBucketConfig()) {
state.transition(WaitUntilReadyStage.COMPLETE);
WaitUntilReadyContext waitUntilReadyContext = new WaitUntilReadyContext(servicesToCheck(core, serviceTypes, bucketName), timeout, desiredState, bucketName, core.diagnostics().collect(Collectors.groupingBy(EndpointDiagnostics::type)), state);
core.context().environment().eventBus().publish(new WaitUntilReadyCompletedEvent(waitUntilReadyContext, WaitUntilReadyCompletedEvent.Reason.CLUSTER_LEVEL_NOT_SUPPORTED));
return Flux.empty();
}
state.transition(WaitUntilReadyStage.PING);
final Flux<ClusterState> diagnostics = Flux.interval(Duration.ofMillis(10), core.context().environment().scheduler()).onBackpressureDrop().map(i -> diagnosticsCurrentState(core)).takeUntil(s -> s == desiredState);
return Flux.concat(ping(core, servicesToCheck(core, serviceTypes, bucketName), timeout, bucketName), diagnostics);
}).then().timeout(timeout, Mono.defer(() -> {
WaitUntilReadyContext waitUntilReadyContext = new WaitUntilReadyContext(servicesToCheck(core, serviceTypes, bucketName), timeout, desiredState, bucketName, core.diagnostics().collect(Collectors.groupingBy(EndpointDiagnostics::type)), state);
CancellationErrorContext errorContext = new CancellationErrorContext(waitUntilReadyContext);
return Mono.error(new UnambiguousTimeoutException("WaitUntilReady timed out", errorContext));
}), core.context().environment().scheduler()).doOnSuccess(unused -> {
state.transition(WaitUntilReadyStage.COMPLETE);
WaitUntilReadyContext waitUntilReadyContext = new WaitUntilReadyContext(servicesToCheck(core, serviceTypes, bucketName), timeout, desiredState, bucketName, core.diagnostics().collect(Collectors.groupingBy(EndpointDiagnostics::type)), state);
core.context().environment().eventBus().publish(new WaitUntilReadyCompletedEvent(waitUntilReadyContext, WaitUntilReadyCompletedEvent.Reason.SUCCESS));
}).toFuture();
}
use of com.couchbase.client.core.config.BucketConfig in project couchbase-jvm-clients by couchbase.
the class KeyValueBucketRefresher method filterEligibleNodes.
/**
* Helper method to generate a stream of KV nodes that can be used to fetch a config.
*
* <p>To be more resilient to failures, this method (similar to 1.x) shifts the node
* list on each invocation by one to make sure we hit all of them eventually.</p>
*
* @param name the bucket name.
* @return a flux of nodes that have the KV service enabled.
*/
private Flux<NodeInfo> filterEligibleNodes(final String name) {
return Flux.defer(() -> {
BucketConfig config = provider.config().bucketConfig(name);
if (config == null) {
eventBus.publish(new BucketConfigRefreshFailedEvent(core.context(), BucketConfigRefreshFailedEvent.RefresherType.KV, BucketConfigRefreshFailedEvent.Reason.NO_BUCKET_FOUND, Optional.empty()));
return Flux.empty();
}
List<NodeInfo> nodes = new ArrayList<>(config.nodes());
shiftNodeList(nodes);
return Flux.fromIterable(nodes).filter(n -> n.services().containsKey(ServiceType.KV) || n.sslServices().containsKey(ServiceType.KV)).take(MAX_PARALLEL_FETCH);
});
}
Aggregations