Skip to content

Commit 7d7bafd

Browse files
committed
Write a test for cluster topology discoverer. Fix the discoverer interface
1 parent 3a32574 commit 7d7bafd

11 files changed

+187
-12
lines changed

src/main/java/org/tarantool/TarantoolClusterClient.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,12 @@ public TarantoolClusterClient(TarantoolClusterClientConfig config, NodeCommunica
7575
}
7676

7777
/**
78-
* @param infoNode a node from which a topology of the cluster is discovered.
7978
* @throws CommunicationException in case of communication with {@code infoNode} exception
8079
* @throws IllegalArgumentException in case when the info node returned invalid address
8180
*/
82-
private Collection<TarantoolInstanceInfo> refreshServerList(TarantoolInstanceInfo infoNode) {
81+
protected Collection<TarantoolInstanceInfo> refreshServerList() {
8382
List<TarantoolInstanceInfo> newServerList = topologyDiscoverer
84-
.discoverTarantoolInstances(infoNode, infoHostConnectionTimeout);
85-
83+
.discoverTarantoolInstances(infoHostConnectionTimeout);
8684

8785
initLock.lock();
8886
try {

src/main/java/org/tarantool/TarantoolClusterClientConfig.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ public class TarantoolClusterClientConfig extends TarantoolClientConfig {
1818
public String[] slaveHosts;
1919

2020
/**
21-
* Address of a tarantool instance that can act as provider of host list
21+
* Address of a tarantool instance form which a cluster host list can be discovered.
2222
*/
2323
public String infoHost;
2424

25+
/**
26+
* Name of a function that called on info host instance to fetch the list of
27+
* tarantool cluster instances
28+
*/
29+
public String infoFunctionName;
30+
2531
/**
2632
* timeout of connecting to a info host
2733
*/

src/main/java/org/tarantool/cluster/ClusterTopologyDiscoverer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
import java.util.List;
66

77
public interface ClusterTopologyDiscoverer {
8-
List<TarantoolInstanceInfo> discoverTarantoolInstances(TarantoolInstanceInfo infoNode, Integer infoHostConnectionTimeout);
8+
List<TarantoolInstanceInfo> discoverTarantoolInstances(Integer infoHostConnectionTimeout);
99
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.tarantool.cluster;
2+
3+
import org.tarantool.TarantoolClientImpl;
4+
import org.tarantool.TarantoolClientOps;
5+
import org.tarantool.TarantoolClusterClientConfig;
6+
import org.tarantool.server.TarantoolInstanceInfo;
7+
8+
import java.util.List;
9+
import java.util.stream.Collectors;
10+
11+
public class ClusterTopologyFromFunctionDiscovererImpl implements ClusterTopologyDiscoverer {
12+
13+
private final TarantoolClusterClientConfig clientConfig;
14+
15+
private final TarantoolInstanceInfo infoNode;
16+
private final String functionName;
17+
18+
public ClusterTopologyFromFunctionDiscovererImpl(TarantoolClusterClientConfig clientConfig) {
19+
this.clientConfig = clientConfig;
20+
if (clientConfig.infoFunctionName == null) {
21+
throw new IllegalArgumentException("infoFuntionName in the config cannot be null");
22+
}
23+
if (clientConfig.infoHost == null) {
24+
throw new IllegalArgumentException("infoHost in the config cannot be null");
25+
}
26+
27+
functionName = clientConfig.infoFunctionName;
28+
this.infoNode = TarantoolInstanceInfo.create(
29+
clientConfig.infoHost, clientConfig.username, clientConfig.password);
30+
}
31+
32+
@Override
33+
public List<TarantoolInstanceInfo> discoverTarantoolInstances(Integer infoHostConnectionTimeout) {
34+
35+
TarantoolClientOps<Integer, List<?>, Object, List<?>> syncOps =
36+
new TarantoolClientImpl(infoNode.getSocketAddress(), clientConfig)
37+
.syncOps();
38+
39+
List<?> list = syncOps
40+
.call(functionName);
41+
42+
List<Object> funcResult = (List<Object>) list.get(0);
43+
return funcResult.stream()
44+
.map(addr -> TarantoolInstanceInfo.create(
45+
parseReplicaUri(addr.toString()), clientConfig.username, clientConfig.password))
46+
.collect(Collectors.toList());
47+
}
48+
49+
private String parseReplicaUri(String uri) {
50+
String[] split = uri.split("@");
51+
if (split.length == 2) {
52+
return split[1];
53+
} else {
54+
return split[0];
55+
}
56+
}
57+
}

src/main/java/org/tarantool/cluster/ClusterTopologyFromShardDiscovererImpl.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,22 @@
1111
public class ClusterTopologyFromShardDiscovererImpl implements ClusterTopologyDiscoverer {
1212

1313
private final TarantoolClusterClientConfig clientConfig;
14+
private final TarantoolInstanceInfo infoNode;
1415

15-
private static final String DISCOVER_TOPOLOGY_TARANTOOL_SIDE_FUNCTION_NAME = "get_shard_cfg";
16+
private static final String DEFAULT_TOPOLOGY_DISCOVER_CALL = "require('vshard').storage.internal.current_cfg";
1617

1718
public ClusterTopologyFromShardDiscovererImpl(TarantoolClusterClientConfig clientConfig) {
1819
this.clientConfig = clientConfig;
20+
this.infoNode = TarantoolInstanceInfo.create(
21+
clientConfig.infoHost, clientConfig.username, clientConfig.password);
1922
}
2023

2124
@Override
22-
public List<TarantoolInstanceInfo> discoverTarantoolInstances(TarantoolInstanceInfo infoNode,
23-
Integer infoHostConnectionTimeout) {
25+
public List<TarantoolInstanceInfo> discoverTarantoolInstances(Integer infoHostConnectionTimeout) {
2426

2527
List<?> list = new TarantoolClientImpl(infoNode.getSocketAddress(), clientConfig)
2628
.syncOps()
27-
.call(DISCOVER_TOPOLOGY_TARANTOOL_SIDE_FUNCTION_NAME);
29+
.call(DEFAULT_TOPOLOGY_DISCOVER_CALL);
2830

2931
Map funcResult = (Map) ((List) list.get(0)).get(0);
3032

src/main/java/org/tarantool/server/TarantoolInstanceInfo.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,27 @@ public static TarantoolInstanceInfo create(InetSocketAddress socketAddress, Stri
6161

6262

6363
/**
64+
* Creates an instance info object with no authentication data.
65+
*
66+
* @param address hostname address as String
67+
*
68+
* @throws IllegalArgumentException if the port parameter is outside the range
69+
* of valid port values, or if the hostname parameter is <TT>null</TT>.
70+
* @throws SecurityException if a security manager is present and
71+
* permission to resolve the host name is
72+
* denied.
73+
*/
74+
public static TarantoolInstanceInfo create(String address) {
75+
return create(address, null, null);
76+
}
77+
78+
79+
80+
/**
81+
* Creates an instance info object
6482
* @param address hostname address as String
83+
* @param username authentication username
84+
* @param password authentication password
6585
*
6686
* @throws IllegalArgumentException if the port parameter is outside the range
6787
* of valid port values, or if the hostname parameter is <TT>null</TT>.

src/test/java/org/tarantool/AbstractTarantoolConnectorIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ protected static TarantoolClientConfig makeClientConfig() {
144144
return fillClientConfig(new TarantoolClientConfig());
145145
}
146146

147-
protected static TarantoolClusterClientConfig makeClusterClientConfig() {
147+
public static TarantoolClusterClientConfig makeClusterClientConfig() {
148148
TarantoolClusterClientConfig config = fillClientConfig(new TarantoolClusterClientConfig());
149149
config.executor = null;
150150
config.operationExpiryTimeMillis = TIMEOUT;

src/test/java/org/tarantool/ClientReconnectClusterIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public void execute() throws Throwable {
110110
assertEquals("Connection time out.", e.getMessage());
111111
}
112112

113-
private TarantoolClientImpl makeClient(String...addrs) {
113+
private TarantoolClusterClient makeClient(String...addrs) {
114114
TarantoolClusterClientConfig config = makeClusterClientConfig();
115115
config.slaveHosts = addrs;
116116
return new TarantoolClusterClient(config);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.tarantool;
2+
3+
public class VshardClusterClientIT {
4+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package org.tarantool.cluster;
2+
3+
import org.junit.jupiter.api.AfterAll;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.BeforeAll;
6+
import org.junit.jupiter.api.DisplayName;
7+
import org.junit.jupiter.api.Test;
8+
import org.tarantool.AbstractTarantoolConnectorIT;
9+
import org.tarantool.TarantoolClusterClientConfig;
10+
import org.tarantool.TarantoolControl;
11+
import org.tarantool.server.TarantoolInstanceInfo;
12+
13+
import java.util.Arrays;
14+
import java.util.List;
15+
16+
import static org.junit.jupiter.api.Assertions.*;
17+
import static org.tarantool.TestUtils.makeInstanceEnv;
18+
19+
@DisplayName("ClusterTopologyFromFunctionDiscovererImpl integration tests")
20+
class ClusterTopologyFromFunctionDiscovererImplIT {
21+
protected static final int INSTANCE_LISTEN_PORT = 3301;
22+
protected static final int INSTANCE_ADMIN_PORT = 3313;
23+
private static final String LUA_FILE = "jdk-testing.lua";
24+
25+
private static final String INSTANCE_NAME = "jdk-testing";
26+
private static TarantoolControl control;
27+
private static TarantoolClusterClientConfig clusterConfig;
28+
29+
private static String INFO_FUNCTION_NAME = "retAddrs";
30+
private static String TEST_RETURN_HOSTLIST_SCRIPT =
31+
"function " + INFO_FUNCTION_NAME + "() return {'localhost:80', '127.0.0.1:3301'} end";
32+
33+
private static final Integer DISCOVER_TIMEOUT_MILLIS = 1000;
34+
35+
@BeforeAll
36+
public static void setupEnv() {
37+
control = new TarantoolControl();
38+
control.createInstance(INSTANCE_NAME, LUA_FILE, makeInstanceEnv(INSTANCE_LISTEN_PORT, INSTANCE_ADMIN_PORT));
39+
40+
control.start(INSTANCE_NAME);
41+
control.waitStarted("jdk-testing");
42+
43+
clusterConfig = AbstractTarantoolConnectorIT.makeClusterClientConfig();
44+
clusterConfig.infoHost = "localhost:" + INSTANCE_LISTEN_PORT;
45+
clusterConfig.infoFunctionName = INFO_FUNCTION_NAME;
46+
}
47+
48+
@AfterAll
49+
public static void tearDownEnv() {
50+
control.stop(INSTANCE_NAME);
51+
}
52+
53+
@Test
54+
@DisplayName("Discoverer successfully fetches and parses a node list from an info node.")
55+
void testSuccessfulAddressParsing() {
56+
//inject the function
57+
control.openConsole(INSTANCE_NAME).exec(TEST_RETURN_HOSTLIST_SCRIPT);
58+
ClusterTopologyFromFunctionDiscovererImpl discoverer =
59+
new ClusterTopologyFromFunctionDiscovererImpl(clusterConfig);
60+
61+
62+
List<TarantoolInstanceInfo> instances = discoverer.discoverTarantoolInstances(DISCOVER_TIMEOUT_MILLIS);
63+
64+
65+
assertNotNull(instances);
66+
assertEquals(2, instances.size());
67+
assertTrue(instances.contains(TarantoolInstanceInfo.create("localhost:80")));
68+
assertTrue(instances.contains(TarantoolInstanceInfo.create("127.0.0.1:3301")));
69+
}
70+
71+
@Test
72+
@DisplayName("Gracefully process case when the function returns empty node list")
73+
void testFunctionReturnedEmptyList() {
74+
String functionCode = "function " + INFO_FUNCTION_NAME + "() return {} end";
75+
//inject the function
76+
control.openConsole(INSTANCE_NAME).exec(functionCode);
77+
ClusterTopologyFromFunctionDiscovererImpl discoverer =
78+
new ClusterTopologyFromFunctionDiscovererImpl(clusterConfig);
79+
80+
81+
List<TarantoolInstanceInfo> instances = discoverer.discoverTarantoolInstances(DISCOVER_TIMEOUT_MILLIS);
82+
83+
84+
assertNotNull(instances);
85+
assertTrue(instances.isEmpty());
86+
}
87+
}

src/test/java/org/tarantool/cluster/ClusterTopologyFromShardDiscovererImplTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.tarantool.TarantoolClusterClientConfig;
66
import org.tarantool.server.TarantoolInstanceInfo;
77

8+
@Deprecated
89
class ClusterTopologyFromShardDiscovererImplTest {
910

1011
@DisplayName("Test that a list which describes the topology is fetched correctly")

0 commit comments

Comments
 (0)