use of com.couchbase.client.core.node.NodeIdentifier in project couchbase-jvm-clients by couchbase.
the class ReactiveBatchHelper method existsBytes.
/**
* Performs the bulk logic of fetching a config and splitting up the observe requests.
*
* @param collection the collection on which the query should be performed.
* @param ids the list of ids which should be checked.
* @return a flux of all
*/
private static Flux<byte[]> existsBytes(final Collection collection, final java.util.Collection<String> ids) {
final Core core = collection.core();
final CoreEnvironment env = core.context().environment();
BucketConfig config = core.clusterConfig().bucketConfig(collection.bucketName());
if (core.configurationProvider().bucketConfigLoadInProgress() || config == null) {
// and then try again. In a steady state this should not happen.
return Mono.delay(Duration.ofMillis(100), env.scheduler()).flatMapMany(ign -> existsBytes(collection, ids));
}
long start = System.nanoTime();
if (!(config instanceof CouchbaseBucketConfig)) {
throw new IllegalStateException("Only couchbase (and ephemeral) buckets are supported at this point!");
}
Map<NodeIdentifier, Map<byte[], Short>> nodeEntries = new HashMap<>(config.nodes().size());
for (NodeInfo node : config.nodes()) {
nodeEntries.put(node.identifier(), new HashMap<>(ids.size() / config.nodes().size()));
}
CouchbaseBucketConfig cbc = (CouchbaseBucketConfig) config;
CollectionIdentifier ci = new CollectionIdentifier(collection.bucketName(), Optional.of(collection.scopeName()), Optional.of(collection.name()));
for (String id : ids) {
byte[] encodedId = id.getBytes(StandardCharsets.UTF_8);
int partitionId = KeyValueLocator.partitionForKey(encodedId, cbc.numberOfPartitions());
int nodeId = cbc.nodeIndexForActive(partitionId, false);
NodeInfo nodeInfo = cbc.nodeAtIndex(nodeId);
nodeEntries.get(nodeInfo.identifier()).put(encodedId, (short) partitionId);
}
List<Mono<MultiObserveViaCasResponse>> responses = new ArrayList<>(nodeEntries.size());
List<MultiObserveViaCasRequest> requests = new ArrayList<>(nodeEntries.size());
for (Map.Entry<NodeIdentifier, Map<byte[], Short>> node : nodeEntries.entrySet()) {
if (node.getValue().isEmpty()) {
// service enabled and 2) have keys that we need to fetch
continue;
}
MultiObserveViaCasRequest request = new MultiObserveViaCasRequest(env.timeoutConfig().kvTimeout(), core.context(), env.retryStrategy(), ci, node.getKey(), node.getValue(), PMGET_PREDICATE);
core.send(request);
requests.add(request);
responses.add(Reactor.wrap(request, request.response(), true));
}
return Flux.merge(responses).flatMap(response -> Flux.fromIterable(response.observed().keySet())).onErrorMap(throwable -> {
BatchErrorContext ctx = new BatchErrorContext(Collections.unmodifiableList(requests));
return new BatchHelperFailureException("Failed to perform BatchHelper bulk operation", throwable, ctx);
}).doOnComplete(() -> core.context().environment().eventBus().publish(new BatchHelperExistsCompletedEvent(Duration.ofNanos(System.nanoTime() - start), new BatchErrorContext(Collections.unmodifiableList(requests)))));
}
use of com.couchbase.client.core.node.NodeIdentifier 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));
}
use of com.couchbase.client.core.node.NodeIdentifier in project couchbase-jvm-clients by couchbase.
the class CoreTest method addNodesAndServicesOnNewConfig.
/**
* This test initializes with a first config and then pushes a second one, making sure that
* the difference in services and nodes is enabled.
*/
@Test
@SuppressWarnings({ "unchecked" })
void addNodesAndServicesOnNewConfig() {
final ConfigurationProvider configProvider = mock(ConfigurationProvider.class);
DirectProcessor<ClusterConfig> configs = DirectProcessor.create();
ClusterConfig clusterConfig = new ClusterConfig();
when(configProvider.configs()).thenReturn(configs);
when(configProvider.config()).thenReturn(clusterConfig);
Node mock101 = mock(Node.class);
when(mock101.identifier()).thenReturn(new NodeIdentifier("10.143.190.101", 8091));
when(mock101.addService(any(ServiceType.class), anyInt(), any(Optional.class))).thenReturn(Mono.empty());
when(mock101.removeService(any(ServiceType.class), any(Optional.class))).thenReturn(Mono.empty());
when(mock101.serviceEnabled(any(ServiceType.class))).thenReturn(true);
when(mock101.disconnect()).thenReturn(Mono.empty());
Node mock102 = mock(Node.class);
when(mock102.identifier()).thenReturn(new NodeIdentifier("10.143.190.102", 8091));
when(mock102.addService(any(ServiceType.class), anyInt(), any(Optional.class))).thenReturn(Mono.empty());
when(mock102.removeService(any(ServiceType.class), any(Optional.class))).thenReturn(Mono.empty());
when(mock102.serviceEnabled(any(ServiceType.class))).thenReturn(true);
when(mock102.disconnect()).thenReturn(Mono.empty());
final Map<String, Node> mocks = new HashMap<>();
mocks.put("10.143.190.101", mock101);
mocks.put("10.143.190.102", mock102);
new Core(ENV, AUTHENTICATOR, SeedNode.LOCALHOST) {
@Override
public ConfigurationProvider createConfigurationProvider() {
return configProvider;
}
@Override
protected Node createNode(final NodeIdentifier target, final Optional<String> alternate) {
return mocks.get(target.address());
}
};
configs.onNext(clusterConfig);
BucketConfig oneNodeConfig = BucketConfigParser.parse(readResource("one_node_config.json", CoreTest.class), ENV, LOCALHOST);
clusterConfig.setBucketConfig(oneNodeConfig);
configs.onNext(clusterConfig);
verify(mock101, times(1)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, never()).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock102, never()).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock102, never()).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock102, never()).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
BucketConfig twoNodeConfig = BucketConfigParser.parse(readResource("two_nodes_config.json", CoreTest.class), ENV, LOCALHOST);
clusterConfig.setBucketConfig(twoNodeConfig);
configs.onNext(clusterConfig);
verify(mock101, times(2)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock101, times(2)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock101, times(2)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock101, times(2)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, times(1)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
}
use of com.couchbase.client.core.node.NodeIdentifier in project couchbase-jvm-clients by couchbase.
the class CoreTest method addServicesOnNewConfig.
@Test
@SuppressWarnings("unchecked")
void addServicesOnNewConfig() {
final ConfigurationProvider configProvider = mock(ConfigurationProvider.class);
DirectProcessor<ClusterConfig> configs = DirectProcessor.create();
ClusterConfig clusterConfig = new ClusterConfig();
when(configProvider.configs()).thenReturn(configs);
when(configProvider.config()).thenReturn(clusterConfig);
Node mock101 = mock(Node.class);
when(mock101.identifier()).thenReturn(new NodeIdentifier("10.143.190.101", 8091));
when(mock101.addService(any(ServiceType.class), anyInt(), any(Optional.class))).thenReturn(Mono.empty());
when(mock101.removeService(any(ServiceType.class), any(Optional.class))).thenReturn(Mono.empty());
when(mock101.serviceEnabled(any(ServiceType.class))).thenReturn(true);
when(mock101.disconnect()).thenReturn(Mono.empty());
Node mock102 = mock(Node.class);
when(mock102.identifier()).thenReturn(new NodeIdentifier("10.143.190.102", 8091));
when(mock102.addService(any(ServiceType.class), anyInt(), any(Optional.class))).thenReturn(Mono.empty());
when(mock102.removeService(any(ServiceType.class), any(Optional.class))).thenReturn(Mono.empty());
when(mock102.serviceEnabled(any(ServiceType.class))).thenReturn(true);
when(mock102.disconnect()).thenReturn(Mono.empty());
final Map<String, Node> mocks = new HashMap<>();
mocks.put("10.143.190.101", mock101);
mocks.put("10.143.190.102", mock102);
new Core(ENV, AUTHENTICATOR, SeedNode.LOCALHOST) {
@Override
public ConfigurationProvider createConfigurationProvider() {
return configProvider;
}
@Override
protected Node createNode(final NodeIdentifier target, final Optional<String> alternate) {
return mocks.get(target.address());
}
};
configs.onNext(clusterConfig);
BucketConfig twoNodesConfig = BucketConfigParser.parse(readResource("two_nodes_config.json", CoreTest.class), ENV, LOCALHOST);
clusterConfig.setBucketConfig(twoNodesConfig);
configs.onNext(clusterConfig);
verify(mock101, times(1)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, times(1)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
BucketConfig twoNodesConfigMore = BucketConfigParser.parse(readResource("two_nodes_config_more_services.json", CoreTest.class), ENV, LOCALHOST);
clusterConfig.setBucketConfig(twoNodesConfigMore);
configs.onNext(clusterConfig);
verify(mock101, times(2)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock101, times(2)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock101, times(2)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock101, times(2)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, times(2)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock102, times(2)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock102, times(2)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock102, times(2)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, times(1)).addService(ServiceType.SEARCH, 8094, Optional.empty());
}
use of com.couchbase.client.core.node.NodeIdentifier in project couchbase-jvm-clients by couchbase.
the class CoreTest method removesNodeIfNotPresentInConfigAnymore.
@Test
@SuppressWarnings("unchecked")
void removesNodeIfNotPresentInConfigAnymore() {
final ConfigurationProvider configProvider = mock(ConfigurationProvider.class);
DirectProcessor<ClusterConfig> configs = DirectProcessor.create();
ClusterConfig clusterConfig = new ClusterConfig();
when(configProvider.configs()).thenReturn(configs);
when(configProvider.config()).thenReturn(clusterConfig);
Node mock101 = mock(Node.class);
when(mock101.identifier()).thenReturn(new NodeIdentifier("10.143.190.101", 8091));
when(mock101.addService(any(ServiceType.class), anyInt(), any(Optional.class))).thenReturn(Mono.empty());
when(mock101.removeService(any(ServiceType.class), any(Optional.class))).thenReturn(Mono.empty());
when(mock101.serviceEnabled(any(ServiceType.class))).thenReturn(true);
when(mock101.disconnect()).thenReturn(Mono.empty());
Node mock102 = mock(Node.class);
when(mock102.identifier()).thenReturn(new NodeIdentifier("10.143.190.102", 8091));
when(mock102.addService(any(ServiceType.class), anyInt(), any(Optional.class))).thenReturn(Mono.empty());
when(mock102.removeService(any(ServiceType.class), any(Optional.class))).thenReturn(Mono.empty());
when(mock102.serviceEnabled(any(ServiceType.class))).thenReturn(true);
when(mock102.disconnect()).thenReturn(Mono.empty());
final Map<String, Node> mocks = new HashMap<>();
mocks.put("10.143.190.101", mock101);
mocks.put("10.143.190.102", mock102);
new Core(ENV, AUTHENTICATOR, SeedNode.LOCALHOST) {
@Override
public ConfigurationProvider createConfigurationProvider() {
return configProvider;
}
@Override
protected Node createNode(final NodeIdentifier target, final Optional<String> alternate) {
return mocks.get(target.address());
}
};
configs.onNext(clusterConfig);
BucketConfig twoNodesConfig = BucketConfigParser.parse(readResource("two_nodes_config_more_services.json", CoreTest.class), ENV, LOCALHOST);
clusterConfig.setBucketConfig(twoNodesConfig);
configs.onNext(clusterConfig);
verify(mock101, times(1)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock101, times(1)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, times(1)).addService(ServiceType.VIEWS, 8092, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.MANAGER, 8091, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.QUERY, 8093, Optional.empty());
verify(mock102, times(1)).addService(ServiceType.KV, 11210, Optional.of("travel-sample"));
verify(mock102, times(1)).addService(ServiceType.SEARCH, 8094, Optional.empty());
BucketConfig twoNodesLessServices = BucketConfigParser.parse(readResource("one_node_config.json", CoreTest.class), ENV, LOCALHOST);
clusterConfig.setBucketConfig(twoNodesLessServices);
configs.onNext(clusterConfig);
verify(mock102, times(1)).disconnect();
}
Aggregations