Search in sources :

Example 41 with Core

use of com.couchbase.client.core.Core in project couchbase-jvm-clients by couchbase.

the class DefaultConfigurationProviderTest method handlesMultipleBucketOpenInProgress.

/**
 * Regression test for JVMCBC-880.
 * <p>
 * Verifies that when multiple bucket open attempts happen in parallel, the bucketConfigLoadInProgress method
 * is not returning false prematurely (namely when only one is finished but one is still oustanding).
 */
@Test
void handlesMultipleBucketOpenInProgress() throws Exception {
    Core core = mock(Core.class);
    CoreContext ctx = new CoreContext(core, 1, ENVIRONMENT, mock(Authenticator.class));
    when(core.context()).thenReturn(ctx);
    Set<SeedNode> seedNodes = new HashSet<>(Collections.singletonList(SeedNode.create("127.0.0.1")));
    Sinks.One<ProposedBucketConfigContext> bucket1Barrier = Sinks.one();
    Sinks.One<ProposedBucketConfigContext> bucket2Barrier = Sinks.one();
    ConfigurationProvider cp = new DefaultConfigurationProvider(core, seedNodes) {

        @Override
        protected Mono<ProposedBucketConfigContext> loadBucketConfigForSeed(NodeIdentifier identifier, int mappedKvPort, int mappedManagerPort, String name, Optional<String> alternateAddress) {
            if (name.equals("bucket1")) {
                return bucket1Barrier.asMono();
            } else {
                return bucket2Barrier.asMono();
            }
        }

        @Override
        public void proposeBucketConfig(ProposedBucketConfigContext ctx) {
        }

        @Override
        protected Mono<Void> registerRefresher(String bucket) {
            return Mono.empty();
        }
    };
    assertFalse(cp.bucketConfigLoadInProgress());
    CountDownLatch latch = new CountDownLatch(2);
    cp.openBucket("bucket1").subscribe(unused -> {
    }, Assertions::fail, () -> {
        assertTrue(cp.bucketConfigLoadInProgress());
        latch.countDown();
    });
    cp.openBucket("bucket2").subscribe(unused -> {
    }, Assertions::fail, () -> {
        assertFalse(cp.bucketConfigLoadInProgress());
        latch.countDown();
    });
    // we pretend bucket 1 takes 1ms, while bucket2 takes 200ms
    Mono.delay(Duration.ofMillis(1)).subscribe(i -> bucket1Barrier.tryEmitValue(new ProposedBucketConfigContext("bucket1", "{}", "127.0.0.1")));
    Mono.delay(Duration.ofMillis(200)).subscribe(i -> bucket2Barrier.tryEmitValue(new ProposedBucketConfigContext("bucket2", "{}", "127.0.0.1")));
    assertTrue(latch.await(5, TimeUnit.SECONDS));
}
Also used : CoreContext(com.couchbase.client.core.CoreContext) Sinks(reactor.core.publisher.Sinks) Optional(java.util.Optional) SeedNode(com.couchbase.client.core.env.SeedNode) CountDownLatch(java.util.concurrent.CountDownLatch) Assertions(org.junit.jupiter.api.Assertions) NodeIdentifier(com.couchbase.client.core.node.NodeIdentifier) PasswordAuthenticator(com.couchbase.client.core.env.PasswordAuthenticator) Authenticator(com.couchbase.client.core.env.Authenticator) Core(com.couchbase.client.core.Core) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 42 with Core

use of com.couchbase.client.core.Core in project couchbase-jvm-clients by couchbase.

the class DefaultConfigurationProviderTest method ignoresMultipleCollectionIdRefreshAttempts.

/**
 * It is allowed to have multiple attempts in-flight at the same time, but not for the same collection identifier
 * (since this would just spam the cluster unnecessarily).
 */
@Test
void ignoresMultipleCollectionIdRefreshAttempts() {
    Core core = mock(Core.class);
    CoreContext ctx = new CoreContext(core, 1, ENVIRONMENT, mock(Authenticator.class));
    when(core.context()).thenReturn(ctx);
    Set<SeedNode> seedNodes = new HashSet<>(Collections.singletonList(SeedNode.create("127.0.0.1")));
    List<GetCollectionIdRequest> capturedRequests = new ArrayList<>();
    doAnswer(invocation -> {
        capturedRequests.add(invocation.getArgument(0));
        return null;
    }).when(core).send(any(GetCollectionIdRequest.class));
    DefaultConfigurationProvider provider = new DefaultConfigurationProvider(core, seedNodes);
    assertFalse(provider.collectionRefreshInProgress());
    CollectionIdentifier identifier1 = new CollectionIdentifier("bucket", Optional.of("scope"), Optional.of("collection"));
    CollectionIdentifier identifier2 = new CollectionIdentifier("bucket", Optional.of("_default"), Optional.of("_default"));
    provider.refreshCollectionId(identifier1);
    assertEquals(1, provider.collectionMapRefreshInProgress.size());
    assertTrue(provider.collectionMapRefreshInProgress.contains(identifier1));
    provider.refreshCollectionId(identifier2);
    assertEquals(2, provider.collectionMapRefreshInProgress.size());
    assertTrue(provider.collectionMapRefreshInProgress.contains(identifier2));
    provider.refreshCollectionId(identifier2);
    assertEquals(2, provider.collectionMapRefreshInProgress.size());
    assertTrue(provider.collectionMapRefreshInProgress.contains(identifier2));
    boolean found = false;
    for (Event event : EVENT_BUS.publishedEvents()) {
        if (event instanceof CollectionMapRefreshIgnoredEvent) {
            assertEquals(((CollectionMapRefreshIgnoredEvent) event).collectionIdentifier(), identifier2);
            found = true;
        }
    }
    assertTrue(found);
    capturedRequests.get(0).succeed(new GetCollectionIdResponse(ResponseStatus.SUCCESS, Optional.of(1234L)));
    assertTrue(provider.collectionRefreshInProgress());
    capturedRequests.get(1).cancel(CancellationReason.TIMEOUT);
    waitUntilCondition(() -> !provider.collectionRefreshInProgress());
    found = false;
    for (Event event : EVENT_BUS.publishedEvents()) {
        if (event instanceof CollectionMapRefreshFailedEvent) {
            assertEquals(((CollectionMapRefreshFailedEvent) event).collectionIdentifier(), identifier2);
            found = true;
        }
    }
    assertTrue(found);
}
Also used : GetCollectionIdResponse(com.couchbase.client.core.msg.kv.GetCollectionIdResponse) CoreContext(com.couchbase.client.core.CoreContext) SeedNode(com.couchbase.client.core.env.SeedNode) ArrayList(java.util.ArrayList) CollectionMapRefreshIgnoredEvent(com.couchbase.client.core.cnc.events.config.CollectionMapRefreshIgnoredEvent) CollectionMapRefreshFailedEvent(com.couchbase.client.core.cnc.events.config.CollectionMapRefreshFailedEvent) CollectionMapRefreshIgnoredEvent(com.couchbase.client.core.cnc.events.config.CollectionMapRefreshIgnoredEvent) CollectionMapRefreshFailedEvent(com.couchbase.client.core.cnc.events.config.CollectionMapRefreshFailedEvent) Event(com.couchbase.client.core.cnc.Event) GetCollectionIdRequest(com.couchbase.client.core.msg.kv.GetCollectionIdRequest) CollectionIdentifier(com.couchbase.client.core.io.CollectionIdentifier) PasswordAuthenticator(com.couchbase.client.core.env.PasswordAuthenticator) Authenticator(com.couchbase.client.core.env.Authenticator) Core(com.couchbase.client.core.Core) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 43 with Core

use of com.couchbase.client.core.Core in project couchbase-jvm-clients by couchbase.

the class ReplicaHelper method getAllReplicasRequests.

/**
 * Helper method to assemble a stream of requests to the active and all replicas
 *
 * @param core the core to execute the request
 * @param collectionIdentifier the collection containing the document
 * @param documentId the ID of the document
 * @param clientContext (nullable) client context info
 * @param retryStrategy the retry strategy to use
 * @param timeout the timeout until we need to stop the get all replicas
 * @param parent the "get all/any replicas" request span
 * @return a stream of requests.
 */
public static CompletableFuture<Stream<GetRequest>> getAllReplicasRequests(final Core core, final CollectionIdentifier collectionIdentifier, final String documentId, final Map<String, Object> clientContext, final RetryStrategy retryStrategy, final Duration timeout, final RequestSpan parent) {
    notNullOrEmpty(documentId, "Id");
    final CoreContext coreContext = core.context();
    final CoreEnvironment environment = coreContext.environment();
    final BucketConfig config = core.clusterConfig().bucketConfig(collectionIdentifier.bucket());
    if (config instanceof CouchbaseBucketConfig) {
        int numReplicas = ((CouchbaseBucketConfig) config).numberOfReplicas();
        List<GetRequest> requests = new ArrayList<>(numReplicas + 1);
        RequestSpan span = environment.requestTracer().requestSpan(TracingIdentifiers.SPAN_REQUEST_KV_GET, parent);
        GetRequest activeRequest = new GetRequest(documentId, timeout, coreContext, collectionIdentifier, retryStrategy, span);
        activeRequest.context().clientContext(clientContext);
        requests.add(activeRequest);
        for (short replica = 1; replica <= numReplicas; replica++) {
            RequestSpan replicaSpan = environment.requestTracer().requestSpan(TracingIdentifiers.SPAN_REQUEST_KV_GET_REPLICA, parent);
            ReplicaGetRequest replicaRequest = new ReplicaGetRequest(documentId, timeout, coreContext, collectionIdentifier, retryStrategy, replica, replicaSpan);
            replicaRequest.context().clientContext(clientContext);
            requests.add(replicaRequest);
        }
        return CompletableFuture.completedFuture(requests.stream());
    } else if (config == null) {
        // no bucket config found, it might be in-flight being opened so we need to reschedule the operation until
        // the timeout fires!
        final Duration retryDelay = Duration.ofMillis(100);
        final CompletableFuture<Stream<GetRequest>> future = new CompletableFuture<>();
        coreContext.environment().timer().schedule(() -> {
            getAllReplicasRequests(core, collectionIdentifier, documentId, clientContext, retryStrategy, timeout.minus(retryDelay), parent).whenComplete((getRequestStream, throwable) -> {
                if (throwable != null) {
                    future.completeExceptionally(throwable);
                } else {
                    future.complete(getRequestStream);
                }
            });
        }, retryDelay);
        return future;
    } else {
        final CompletableFuture<Stream<GetRequest>> future = new CompletableFuture<>();
        future.completeExceptionally(CommonExceptions.getFromReplicaNotCouchbaseBucket());
        return future;
    }
}
Also used : CouchbaseException(com.couchbase.client.core.error.CouchbaseException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) CouchbaseBucketConfig(com.couchbase.client.core.config.CouchbaseBucketConfig) ArrayList(java.util.ArrayList) DefaultErrorUtil.keyValueStatusToException(com.couchbase.client.core.error.DefaultErrorUtil.keyValueStatusToException) TracingIdentifiers(com.couchbase.client.core.cnc.TracingIdentifiers) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DocumentUnretrievableException(com.couchbase.client.core.error.DocumentUnretrievableException) CoreContext(com.couchbase.client.core.CoreContext) Duration(java.time.Duration) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Stability(com.couchbase.client.core.annotation.Stability) RequestSpan(com.couchbase.client.core.cnc.RequestSpan) GetResponse(com.couchbase.client.core.msg.kv.GetResponse) IndividualReplicaGetFailedEvent(com.couchbase.client.core.cnc.events.request.IndividualReplicaGetFailedEvent) BucketConfig(com.couchbase.client.core.config.BucketConfig) Reactor(com.couchbase.client.core.Reactor) CommonExceptions(com.couchbase.client.core.error.CommonExceptions) Mono(reactor.core.publisher.Mono) CompletionException(java.util.concurrent.CompletionException) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) Collectors(java.util.stream.Collectors) Validators.notNullOrEmpty(com.couchbase.client.core.util.Validators.notNullOrEmpty) Flux(reactor.core.publisher.Flux) List(java.util.List) Stream(java.util.stream.Stream) GetRequest(com.couchbase.client.core.msg.kv.GetRequest) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest) ErrorContext(com.couchbase.client.core.error.context.ErrorContext) CollectionIdentifier(com.couchbase.client.core.io.CollectionIdentifier) RetryStrategy(com.couchbase.client.core.retry.RetryStrategy) Core(com.couchbase.client.core.Core) ReducedKeyValueErrorContext(com.couchbase.client.core.error.context.ReducedKeyValueErrorContext) Collections(java.util.Collections) AggregateErrorContext(com.couchbase.client.core.error.context.AggregateErrorContext) CoreContext(com.couchbase.client.core.CoreContext) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) CouchbaseBucketConfig(com.couchbase.client.core.config.CouchbaseBucketConfig) ArrayList(java.util.ArrayList) Duration(java.time.Duration) CouchbaseBucketConfig(com.couchbase.client.core.config.CouchbaseBucketConfig) BucketConfig(com.couchbase.client.core.config.BucketConfig) RequestSpan(com.couchbase.client.core.cnc.RequestSpan) CompletableFuture(java.util.concurrent.CompletableFuture) GetRequest(com.couchbase.client.core.msg.kv.GetRequest) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest)

Example 44 with Core

use of com.couchbase.client.core.Core in project couchbase-jvm-clients by couchbase.

the class ReplicaHelper method getAllReplicasReactive.

/**
 * @param clientContext (nullable)
 * @param parentSpan (nullable)
 */
public static Flux<GetReplicaResponse> getAllReplicasReactive(final Core core, final CollectionIdentifier collectionIdentifier, final String documentId, final Duration timeout, final RetryStrategy retryStrategy, Map<String, Object> clientContext, RequestSpan parentSpan) {
    notNullOrEmpty(documentId, "Id", () -> ReducedKeyValueErrorContext.create(documentId, collectionIdentifier));
    CoreEnvironment env = core.context().environment();
    RequestSpan getAllSpan = env.requestTracer().requestSpan(TracingIdentifiers.SPAN_GET_ALL_REPLICAS, parentSpan);
    getAllSpan.attribute(TracingIdentifiers.ATTR_SYSTEM, TracingIdentifiers.ATTR_SYSTEM_COUCHBASE);
    return Reactor.toMono(() -> getAllReplicasRequests(core, collectionIdentifier, documentId, clientContext, retryStrategy, timeout, getAllSpan)).flux().flatMap(Flux::fromStream).flatMap(request -> Reactor.wrap(request, get(core, request), true).onErrorResume(t -> {
        env.eventBus().publish(new IndividualReplicaGetFailedEvent(request.context()));
        // Swallow any errors from individual replicas
        return Mono.empty();
    }).map(response -> new GetReplicaResponse(response, request instanceof ReplicaGetRequest))).doFinally(signalType -> getAllSpan.end());
}
Also used : CouchbaseException(com.couchbase.client.core.error.CouchbaseException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) CouchbaseBucketConfig(com.couchbase.client.core.config.CouchbaseBucketConfig) ArrayList(java.util.ArrayList) DefaultErrorUtil.keyValueStatusToException(com.couchbase.client.core.error.DefaultErrorUtil.keyValueStatusToException) TracingIdentifiers(com.couchbase.client.core.cnc.TracingIdentifiers) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DocumentUnretrievableException(com.couchbase.client.core.error.DocumentUnretrievableException) CoreContext(com.couchbase.client.core.CoreContext) Duration(java.time.Duration) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Stability(com.couchbase.client.core.annotation.Stability) RequestSpan(com.couchbase.client.core.cnc.RequestSpan) GetResponse(com.couchbase.client.core.msg.kv.GetResponse) IndividualReplicaGetFailedEvent(com.couchbase.client.core.cnc.events.request.IndividualReplicaGetFailedEvent) BucketConfig(com.couchbase.client.core.config.BucketConfig) Reactor(com.couchbase.client.core.Reactor) CommonExceptions(com.couchbase.client.core.error.CommonExceptions) Mono(reactor.core.publisher.Mono) CompletionException(java.util.concurrent.CompletionException) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) Collectors(java.util.stream.Collectors) Validators.notNullOrEmpty(com.couchbase.client.core.util.Validators.notNullOrEmpty) Flux(reactor.core.publisher.Flux) List(java.util.List) Stream(java.util.stream.Stream) GetRequest(com.couchbase.client.core.msg.kv.GetRequest) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest) ErrorContext(com.couchbase.client.core.error.context.ErrorContext) CollectionIdentifier(com.couchbase.client.core.io.CollectionIdentifier) RetryStrategy(com.couchbase.client.core.retry.RetryStrategy) Core(com.couchbase.client.core.Core) ReducedKeyValueErrorContext(com.couchbase.client.core.error.context.ReducedKeyValueErrorContext) Collections(java.util.Collections) AggregateErrorContext(com.couchbase.client.core.error.context.AggregateErrorContext) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) IndividualReplicaGetFailedEvent(com.couchbase.client.core.cnc.events.request.IndividualReplicaGetFailedEvent) Flux(reactor.core.publisher.Flux) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest) RequestSpan(com.couchbase.client.core.cnc.RequestSpan)

Example 45 with Core

use of com.couchbase.client.core.Core in project couchbase-jvm-clients by couchbase.

the class ReplicaHelper method getAllReplicasAsync.

/**
 * Reads from replicas or the active node based on the options and returns the results as a list
 * of futures that might complete or fail.
 *
 * @param clientContext (nullable)
 * @param parentSpan (nullable)
 * @param responseMapper converts the GetReplicaResponse to the client's native result type
 * @return a list of results from the active and the replica.
 */
public static <R> CompletableFuture<List<CompletableFuture<R>>> getAllReplicasAsync(final Core core, final CollectionIdentifier collectionIdentifier, final String documentId, final Duration timeout, final RetryStrategy retryStrategy, final Map<String, Object> clientContext, final RequestSpan parentSpan, final Function<GetReplicaResponse, R> responseMapper) {
    CoreEnvironment env = core.context().environment();
    RequestSpan getAllSpan = env.requestTracer().requestSpan(TracingIdentifiers.SPAN_GET_ALL_REPLICAS, parentSpan);
    getAllSpan.attribute(TracingIdentifiers.ATTR_SYSTEM, TracingIdentifiers.ATTR_SYSTEM_COUCHBASE);
    return getAllReplicasRequests(core, collectionIdentifier, documentId, clientContext, retryStrategy, timeout, getAllSpan).thenApply(stream -> stream.map(request -> get(core, request).thenApply(response -> new GetReplicaResponse(response, request instanceof ReplicaGetRequest)).thenApply(responseMapper)).collect(Collectors.toList())).whenComplete((completableFutures, throwable) -> {
        final AtomicInteger toComplete = new AtomicInteger(completableFutures.size());
        for (CompletableFuture<R> cf : completableFutures) {
            cf.whenComplete((a, b) -> {
                if (toComplete.decrementAndGet() == 0) {
                    getAllSpan.end();
                }
            });
        }
    });
}
Also used : CouchbaseException(com.couchbase.client.core.error.CouchbaseException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) CouchbaseBucketConfig(com.couchbase.client.core.config.CouchbaseBucketConfig) ArrayList(java.util.ArrayList) DefaultErrorUtil.keyValueStatusToException(com.couchbase.client.core.error.DefaultErrorUtil.keyValueStatusToException) TracingIdentifiers(com.couchbase.client.core.cnc.TracingIdentifiers) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DocumentUnretrievableException(com.couchbase.client.core.error.DocumentUnretrievableException) CoreContext(com.couchbase.client.core.CoreContext) Duration(java.time.Duration) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Stability(com.couchbase.client.core.annotation.Stability) RequestSpan(com.couchbase.client.core.cnc.RequestSpan) GetResponse(com.couchbase.client.core.msg.kv.GetResponse) IndividualReplicaGetFailedEvent(com.couchbase.client.core.cnc.events.request.IndividualReplicaGetFailedEvent) BucketConfig(com.couchbase.client.core.config.BucketConfig) Reactor(com.couchbase.client.core.Reactor) CommonExceptions(com.couchbase.client.core.error.CommonExceptions) Mono(reactor.core.publisher.Mono) CompletionException(java.util.concurrent.CompletionException) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) Collectors(java.util.stream.Collectors) Validators.notNullOrEmpty(com.couchbase.client.core.util.Validators.notNullOrEmpty) Flux(reactor.core.publisher.Flux) List(java.util.List) Stream(java.util.stream.Stream) GetRequest(com.couchbase.client.core.msg.kv.GetRequest) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest) ErrorContext(com.couchbase.client.core.error.context.ErrorContext) CollectionIdentifier(com.couchbase.client.core.io.CollectionIdentifier) RetryStrategy(com.couchbase.client.core.retry.RetryStrategy) Core(com.couchbase.client.core.Core) ReducedKeyValueErrorContext(com.couchbase.client.core.error.context.ReducedKeyValueErrorContext) Collections(java.util.Collections) AggregateErrorContext(com.couchbase.client.core.error.context.AggregateErrorContext) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ReplicaGetRequest(com.couchbase.client.core.msg.kv.ReplicaGetRequest) RequestSpan(com.couchbase.client.core.cnc.RequestSpan)

Aggregations

Core (com.couchbase.client.core.Core)49 CoreContext (com.couchbase.client.core.CoreContext)31 Test (org.junit.jupiter.api.Test)25 CoreEnvironment (com.couchbase.client.core.env.CoreEnvironment)17 Duration (java.time.Duration)13 ArrayList (java.util.ArrayList)12 Map (java.util.Map)12 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)12 Stability (com.couchbase.client.core.annotation.Stability)11 Optional (java.util.Optional)11 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)11 BucketConfig (com.couchbase.client.core.config.BucketConfig)10 Authenticator (com.couchbase.client.core.env.Authenticator)10 List (java.util.List)10 Flux (reactor.core.publisher.Flux)10 Mono (reactor.core.publisher.Mono)10 Reactor (com.couchbase.client.core.Reactor)9 SeedNode (com.couchbase.client.core.env.SeedNode)9 CollectionIdentifier (com.couchbase.client.core.io.CollectionIdentifier)9 HashSet (java.util.HashSet)9