Skip to content

Commit 3dc992b

Browse files
committed
KCBC-192: Followup (part 2)
Motivation ---------- The analytics "require Couchbase Server" check was applied only to the Java SDK, but it was intended to apply to Kotlin too. Modifications ------------- Move AnalyticsAccessor.skipClusterTypeCheck() and requireCouchbaseServer() to a new core-io class: AnalyticsHelper Call requireCouchbaseServer() from Kotlin's AnalyticsExecutor. Change-Id: I44961cc82869fa961ab93652c7234087c0acf884 Reviewed-on: https://review.couchbase.org/c/couchbase-jvm-clients/+/231585 Tested-by: Build Bot <[email protected]> Reviewed-by: Graham Pople <[email protected]> Reviewed-by: Michael Reiche <[email protected]>
1 parent 9503a25 commit 3dc992b

3 files changed

Lines changed: 71 additions & 37 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2025 Couchbase, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.couchbase.client.core.classic.analytics;
18+
19+
import com.couchbase.client.core.Core;
20+
import com.couchbase.client.core.annotation.Stability;
21+
import com.couchbase.client.core.error.CouchbaseException;
22+
import com.couchbase.client.core.topology.ClusterIdentifier;
23+
import org.jspecify.annotations.Nullable;
24+
import reactor.core.publisher.Mono;
25+
26+
import java.time.Duration;
27+
28+
@Stability.Internal
29+
public class AnalyticsHelper {
30+
private AnalyticsHelper() {
31+
}
32+
33+
private static volatile boolean skipClusterTypeCheck = false;
34+
35+
/**
36+
* Call this method once when your app starts up to disable the check that
37+
* prevents the operational SDK from being used with an Enterprise Analytics cluster.
38+
* <p>
39+
* This is super-extra-unsupported internal API.
40+
*/
41+
public static void skipClusterTypeCheck() {
42+
skipClusterTypeCheck = true;
43+
}
44+
45+
public static Mono<Void> requireCouchbaseServer(Core core, Duration timeout) {
46+
if (skipClusterTypeCheck) {
47+
return Mono.empty();
48+
}
49+
50+
return core.waitForClusterTopology(timeout)
51+
.mapNotNull(clusterTopology -> {
52+
if (isEnterpriseAnalytics(clusterTopology.id())) {
53+
throw new CouchbaseException(
54+
"This SDK is for Couchbase Server (operational) clusters, but the remote cluster is an Enterprise Analytics cluster." +
55+
" Please use the Enterprise Analytics SDK to access this cluster."
56+
);
57+
}
58+
return null; // success! complete the empty mono.
59+
});
60+
}
61+
62+
private static boolean isEnterpriseAnalytics(@Nullable ClusterIdentifier clusterId) {
63+
return clusterId != null && "analytics".equals(clusterId.product());
64+
}
65+
}

java-client/src/main/java/com/couchbase/client/java/analytics/AnalyticsAccessor.java

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,15 @@
1919
import com.couchbase.client.core.Core;
2020
import com.couchbase.client.core.Reactor;
2121
import com.couchbase.client.core.annotation.Stability;
22-
import com.couchbase.client.core.error.CouchbaseException;
2322
import com.couchbase.client.core.msg.analytics.AnalyticsRequest;
2423
import com.couchbase.client.core.msg.analytics.AnalyticsResponse;
25-
import com.couchbase.client.core.topology.ClusterIdentifier;
2624
import com.couchbase.client.java.codec.JsonSerializer;
27-
import org.jspecify.annotations.Nullable;
2825
import reactor.core.publisher.Mono;
2926

30-
import java.time.Duration;
3127
import java.util.concurrent.CompletableFuture;
3228

29+
import static com.couchbase.client.core.classic.analytics.AnalyticsHelper.requireCouchbaseServer;
30+
3331
/**
3432
* Internal helper to map the results from the analytics requests.
3533
*
@@ -38,18 +36,6 @@
3836
@Stability.Internal
3937
public class AnalyticsAccessor {
4038

41-
private static volatile boolean skipClusterTypeCheck = false;
42-
43-
/**
44-
* Call this method once when your app starts up to disable the check that
45-
* prevents the operational SDK from being used with an Enterprise Analytics cluster.
46-
* <p>
47-
* This is super-extra-unsupported internal API.
48-
*/
49-
public static void skipClusterTypeCheck() {
50-
skipClusterTypeCheck = true;
51-
}
52-
5339
public static CompletableFuture<AnalyticsResult> analyticsQueryAsync(final Core core,
5440
final AnalyticsRequest request,
5541
final JsonSerializer serializer) {
@@ -78,25 +64,4 @@ private static Mono<AnalyticsResponse> analyticsQueryInternal(final Core core, f
7864
.doOnError(err -> request.context().logicallyComplete(err));
7965
}));
8066
}
81-
82-
private static Mono<Void> requireCouchbaseServer(Core core, Duration timeout) {
83-
if (skipClusterTypeCheck) {
84-
return Mono.empty();
85-
}
86-
87-
return core.waitForClusterTopology(timeout)
88-
.mapNotNull(clusterTopology -> {
89-
if (isEnterpriseAnalytics(clusterTopology.id())) {
90-
throw new CouchbaseException(
91-
"This SDK is for Couchbase Server (operational) clusters, but the remote cluster is an Enterprise Analytics cluster." +
92-
" Please use the Enterprise Analytics SDK to access this cluster."
93-
);
94-
}
95-
return null; // success! complete the empty mono.
96-
});
97-
}
98-
99-
private static boolean isEnterpriseAnalytics(@Nullable ClusterIdentifier clusterId) {
100-
return clusterId != null && "analytics".equals(clusterId.product());
101-
}
10267
}

kotlin-client/src/main/kotlin/com/couchbase/client/kotlin/analytics/internal/AnalyticsExecutor.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.couchbase.client.kotlin.analytics.internal
1818

1919
import com.couchbase.client.core.Core
20+
import com.couchbase.client.core.classic.analytics.AnalyticsHelper
2021
import com.couchbase.client.core.cnc.TracingIdentifiers
2122
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.node.ArrayNode
2223
import com.couchbase.client.core.deps.com.fasterxml.jackson.databind.node.ObjectNode
@@ -41,6 +42,7 @@ import kotlinx.coroutines.flow.flow
4142
import kotlinx.coroutines.flow.map
4243
import kotlinx.coroutines.future.await
4344
import kotlinx.coroutines.reactive.asFlow
45+
import kotlinx.coroutines.reactor.awaitSingleOrNull
4446

4547
internal class AnalyticsExecutor(
4648
private val core: Core,
@@ -114,6 +116,8 @@ internal class AnalyticsExecutor(
114116
request.context().clientContext(common.clientContext)
115117

116118
try {
119+
AnalyticsHelper.requireCouchbaseServer(core, timeout).awaitSingleOrNull()
120+
117121
core.send(request)
118122

119123
val response = request.response().await()

0 commit comments

Comments
 (0)