|
41 | 41 | import com.clickhouse.data.value.UnsignedInteger; |
42 | 42 | import com.clickhouse.data.value.UnsignedLong; |
43 | 43 | import com.clickhouse.data.value.UnsignedShort; |
44 | | - |
45 | 44 | import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream; |
46 | 45 | import org.testng.Assert; |
47 | 46 | import org.testng.SkipException; |
48 | 47 | import org.testng.annotations.DataProvider; |
49 | 48 | import org.testng.annotations.Test; |
50 | | -import org.testng.asserts.Assertion; |
51 | 49 |
|
52 | 50 | import java.io.BufferedReader; |
53 | 51 | import java.io.ByteArrayInputStream; |
|
75 | 73 | import java.util.Collections; |
76 | 74 | import java.util.List; |
77 | 75 | import java.util.Map; |
| 76 | +import java.util.Map.Entry; |
| 77 | +import java.util.Properties; |
78 | 78 | import java.util.TimeZone; |
79 | 79 | import java.util.UUID; |
80 | | -import java.util.Map.Entry; |
81 | 80 | import java.util.concurrent.CompletableFuture; |
82 | 81 | import java.util.concurrent.ExecutionException; |
83 | 82 | import java.util.concurrent.atomic.AtomicInteger; |
@@ -150,13 +149,23 @@ protected ClickHouseResponseSummary execute(ClickHouseRequest<?> request, String |
150 | 149 |
|
151 | 150 | protected ClickHouseRequest<?> newRequest(ClickHouseClient client, ClickHouseNode server) { |
152 | 151 | ClickHouseRequest<?> request = client.read(server); |
| 152 | + setClientOptions(request); |
| 153 | + return request; |
| 154 | + } |
| 155 | + |
| 156 | + protected ClickHouseRequest<?> newRequest(ClickHouseClient client, ClickHouseNodes servers) { |
| 157 | + ClickHouseRequest<?> request = client.read(servers); |
| 158 | + setClientOptions(request); |
| 159 | + return request; |
| 160 | + } |
| 161 | + |
| 162 | + private void setClientOptions(ClickHouseRequest<?> request) { |
153 | 163 | Map<ClickHouseOption, Serializable> options = getClientOptions(); |
154 | 164 | if (options != null) { |
155 | 165 | for (Entry<ClickHouseOption, Serializable> e : options.entrySet()) { |
156 | 166 | request.option(e.getKey(), e.getValue()); |
157 | 167 | } |
158 | 168 | } |
159 | | - return request; |
160 | 169 | } |
161 | 170 |
|
162 | 171 | protected abstract ClickHouseProtocol getProtocol(); |
@@ -398,6 +407,16 @@ protected Object[][] getSimpleTypes() { |
398 | 407 | "00000000-0000-0000-ffff-ffffffffffff", "00000000-0000-0000-0000-000000000001" } }; |
399 | 408 | } |
400 | 409 |
|
| 410 | + @DataProvider(name = "loadBalancingPolicies") |
| 411 | + protected Object[][] getLoadBalancingPolicies() { |
| 412 | + return new Object[][]{ |
| 413 | + {ClickHouseLoadBalancingPolicy.of(null)}, |
| 414 | + {ClickHouseLoadBalancingPolicy.of(ClickHouseLoadBalancingPolicy.FIRST_ALIVE)}, |
| 415 | + {ClickHouseLoadBalancingPolicy.of(ClickHouseLoadBalancingPolicy.ROUND_ROBIN)}, |
| 416 | + {ClickHouseLoadBalancingPolicy.of(ClickHouseLoadBalancingPolicy.RANDOM)}, |
| 417 | + }; |
| 418 | + } |
| 419 | + |
401 | 420 | @Test(groups = { "unit" }) |
402 | 421 | public void testInitialization() { |
403 | 422 | Assert.assertNotNull(getProtocol(), "The client should support non-null protocol"); |
@@ -886,7 +905,7 @@ public void testQuery() { |
886 | 905 | * while (response.hasError()) { int index = 0; for (ClickHouseColumn c : |
887 | 906 | * columns) { // RawValue v = response.getRawValue(index++); // String v = |
888 | 907 | * response.getValue(index++, String.class) } |
889 | | - * |
| 908 | + * |
890 | 909 | * } byte[] bytes = in.readAllBytes(); String str = new String(bytes); |
891 | 910 | */ |
892 | 911 | } catch (Exception e) { |
@@ -2555,4 +2574,50 @@ public void testRowBinaryWithDefaults() throws ClickHouseException, IOException, |
2555 | 2574 | } |
2556 | 2575 | } |
2557 | 2576 | } |
| 2577 | + |
| 2578 | + @Test(dataProvider = "loadBalancingPolicies", groups = {"unit"}) |
| 2579 | + public void testLoadBalancingPolicyFailover(ClickHouseLoadBalancingPolicy loadBalancingPolicy) { |
| 2580 | + String firstEndpoint = "111.1.1.1"; |
| 2581 | + String secondEndpoint = "222.2.2.2"; |
| 2582 | + |
| 2583 | + Properties props = new Properties(); |
| 2584 | + props.setProperty("failover", "1"); |
| 2585 | + |
| 2586 | + // nodes where the first node is failed |
| 2587 | + ClickHouseNodes nodes = ClickHouseNodes.of( |
| 2588 | + getProtocol() + "://" + firstEndpoint + "," + secondEndpoint, |
| 2589 | + props |
| 2590 | + ); |
| 2591 | + |
| 2592 | + try (ClickHouseClient client = getClient(); |
| 2593 | + ClickHouseResponse response = newRequest(client, nodes.nodes.getFirst()) |
| 2594 | + .query("select 1") |
| 2595 | + .executeAndWait()) { |
| 2596 | + Assert.fail("Exception expected for query on failed node"); |
| 2597 | + } catch (Exception failoverException) { |
| 2598 | + ClickHouseNode failoverNode = loadBalancingPolicy.suggest(nodes, nodes.nodes.getFirst(), failoverException); |
| 2599 | + Assert.assertEquals(failoverNode.getHost(), secondEndpoint, "The next node is expected to be suggested by the load balancing policy"); |
| 2600 | + } |
| 2601 | + } |
| 2602 | + |
| 2603 | + @Test(groups = {"integration"}) |
| 2604 | + public void testFailover() throws ClickHouseException { |
| 2605 | + ClickHouseNode availableNode = getServer(); |
| 2606 | + Properties props = new Properties(); |
| 2607 | + props.setProperty("failover", "1"); |
| 2608 | + |
| 2609 | + // nodes with the first node is unavailable |
| 2610 | + ClickHouseNodes nodes = ClickHouseNodes.of( |
| 2611 | + getProtocol() + "://111.1.1.1," + availableNode.getBaseUri(), |
| 2612 | + props |
| 2613 | + ); |
| 2614 | + |
| 2615 | + // should fail over to next node and successfully perform request if the first node is failed |
| 2616 | + try (ClickHouseClient client = getClient(); |
| 2617 | + ClickHouseResponse response = newRequest(client, nodes) |
| 2618 | + .query("select 1") |
| 2619 | + .executeAndWait()) { |
| 2620 | + Assert.assertEquals(response.firstRecord().getValue(0).asInteger(), 1); |
| 2621 | + } |
| 2622 | + } |
2558 | 2623 | } |
0 commit comments