Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit 542de27

Browse files
committed
factor out conversion util
Change-Id: I8fc15d7d028c773385cd557aa6d2fb3a2453a1da
1 parent bccb0ec commit 542de27

4 files changed

Lines changed: 127 additions & 27 deletions

File tree

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/grpc/BigtableChannelPool.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,12 @@
4646
/**
4747
* A {@link ManagedChannel} that will send requests round-robin via a set of channels.
4848
*
49-
* <p>In addition to spreading requests over a set of child connections, the pool will also actively
50-
* manage the lifecycle of the channels. Currently lifecycle management is limited to pre-emptively
51-
* replacing channels every hour. In the future it will dynamically size the pool based on number of
52-
* outstanding requests.
49+
* <p>Spreads over a set of child connections, and actively manages lifecycle of connections.
50+
* Dynamically resizes pool based on number of outstanding connections.
5351
*
54-
* <p>Package-private for internal use.
52+
* <p>Internal API
5553
*/
54+
@InternalApi("")
5655
public class BigtableChannelPool extends ManagedChannel {
5756
@VisibleForTesting
5857
static final Logger LOG = Logger.getLogger(BigtableChannelPool.class.getName());
@@ -82,7 +81,7 @@ public static BigtableChannelPool create(
8281
* @param executor periodically refreshes the channels
8382
*/
8483
@VisibleForTesting
85-
public BigtableChannelPool(
84+
BigtableChannelPool(
8685
BigtableChannelPoolSettings settings,
8786
ChannelFactory channelFactory,
8887
ScheduledExecutorService executor)

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/gaxx/grpc/BigtableTransportChannelProvider.java

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
*/
1616
package com.google.cloud.bigtable.gaxx.grpc;
1717

18-
import com.google.api.core.InternalExtensionOnly;
18+
import com.google.api.core.InternalApi;
1919
import com.google.api.gax.grpc.ChannelFactory;
2020
import com.google.api.gax.grpc.ChannelPoolSettings;
2121
import com.google.api.gax.grpc.GrpcTransportChannel;
2222
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
2323
import com.google.api.gax.rpc.TransportChannel;
2424
import com.google.api.gax.rpc.TransportChannelProvider;
2525
import com.google.auth.Credentials;
26+
import com.google.cloud.bigtable.gaxx.utils.ChannelPoolSettingsCopier;
27+
import com.google.common.annotations.VisibleForTesting;
2628
import com.google.common.base.Preconditions;
2729
import io.grpc.ManagedChannel;
2830
import java.io.IOException;
@@ -31,12 +33,11 @@
3133
import java.util.concurrent.ScheduledExecutorService;
3234

3335
/** An instance of TransportChannelProvider that always provides the same TransportChannel. */
34-
@InternalExtensionOnly
36+
@InternalApi
3537
public final class BigtableTransportChannelProvider implements TransportChannelProvider {
3638

3739
private final InstantiatingGrpcChannelProvider delegate;
38-
private final Object lock = new Object();
39-
private volatile TransportChannel transportChannel;
40+
private TransportChannel transportChannel;
4041

4142
private BigtableTransportChannelProvider(
4243
InstantiatingGrpcChannelProvider instantiatingGrpcChannelProvider) {
@@ -106,13 +107,8 @@ public TransportChannelProvider withPoolSize(int size) {
106107
@Override
107108
public TransportChannel getTransportChannel() throws IOException {
108109
TransportChannel result = transportChannel;
109-
if (result == null) {
110-
synchronized (lock) {
111-
result = transportChannel;
112-
if (result == null) {
110+
if (transportChannel == null) {
113111
transportChannel = result = createTransportChannel();
114-
}
115-
}
116112
}
117113
return result;
118114
}
@@ -138,17 +134,7 @@ private TransportChannel createTransportChannel() throws IOException {
138134
}
139135
};
140136

141-
// Transfer pooling settings from the original delegate to the BigtableChannelPool.
142-
ChannelPoolSettings ogPoolSettings = delegate.getChannelPoolSettings();
143-
BigtableChannelPoolSettings btPoolSettings =
144-
BigtableChannelPoolSettings.builder()
145-
.setInitialChannelCount(ogPoolSettings.getInitialChannelCount())
146-
.setMinChannelCount(ogPoolSettings.getMinChannelCount())
147-
.setMaxChannelCount(ogPoolSettings.getMaxChannelCount())
148-
.setMinRpcsPerChannel(ogPoolSettings.getMinRpcsPerChannel())
149-
.setMaxRpcsPerChannel(ogPoolSettings.getMaxRpcsPerChannel())
150-
.setPreemptiveRefreshEnabled(ogPoolSettings.isPreemptiveRefreshEnabled())
151-
.build();
137+
BigtableChannelPoolSettings btPoolSettings = ChannelPoolSettingsCopier.toBigtableChannelPoolSettings(delegate.getChannelPoolSettings());
152138

153139
BigtableChannelPool btChannelPool = BigtableChannelPool.create(btPoolSettings, channelFactory);
154140

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.google.cloud.bigtable.gaxx.utils;
2+
3+
import com.google.api.gax.grpc.ChannelPoolSettings;
4+
import com.google.cloud.bigtable.gaxx.grpc.BigtableChannelPoolSettings;
5+
6+
/**
7+
* Utility class to convert ChannelPoolSettings to BigtableChannelPoolSettings.
8+
*/
9+
public class ChannelPoolSettingsCopier {
10+
public static BigtableChannelPoolSettings toBigtableChannelPoolSettings(ChannelPoolSettings original) {
11+
if (original == null) {
12+
return null;
13+
}
14+
15+
return BigtableChannelPoolSettings.builder()
16+
.setMinRpcsPerChannel(original.getMinRpcsPerChannel())
17+
.setMaxRpcsPerChannel(original.getMaxRpcsPerChannel())
18+
.setMinChannelCount(original.getMinChannelCount())
19+
.setMaxChannelCount(original.getMaxChannelCount())
20+
.setInitialChannelCount(original.getInitialChannelCount())
21+
.setPreemptiveRefreshEnabled(original.isPreemptiveRefreshEnabled())
22+
.build();
23+
}
24+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.google.cloud.bigtable.gaxx.utils;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
5+
import com.google.api.gax.grpc.ChannelPoolSettings;
6+
import com.google.cloud.bigtable.gaxx.grpc.BigtableChannelPoolSettings;
7+
import java.lang.reflect.Modifier;
8+
import java.util.List;
9+
import java.lang.reflect.Method;
10+
import java.util.Arrays;
11+
import java.util.stream.Collectors;
12+
import org.junit.Rule;
13+
import org.junit.Test;
14+
import org.junit.runner.RunWith;
15+
import org.junit.runners.JUnit4;
16+
import org.mockito.junit.MockitoJUnit;
17+
import org.mockito.junit.MockitoRule;
18+
19+
@RunWith(JUnit4.class)
20+
public class ChannelPoolCopyTest {
21+
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
22+
23+
@Test
24+
public void testToBigtableChannelPoolSettingsAllFieldsSetCopiesCorrectly() throws Exception {
25+
ChannelPoolSettings originalSettings =
26+
ChannelPoolSettings.builder()
27+
.setMinRpcsPerChannel(10)
28+
.setMaxRpcsPerChannel(50)
29+
.setMinChannelCount(5)
30+
.setMaxChannelCount(100)
31+
.setInitialChannelCount(20)
32+
.setPreemptiveRefreshEnabled(true)
33+
.build();
34+
35+
BigtableChannelPoolSettings copiedSettings =
36+
ChannelPoolSettingsCopier.toBigtableChannelPoolSettings(originalSettings);
37+
assertSettingsCopiedCorrectly(originalSettings, copiedSettings);
38+
}
39+
40+
@Test
41+
public void testToBigtableChannelPoolSettingsDefaultValuesCopiesCorrectly() throws Exception {
42+
// 1. Arrange
43+
ChannelPoolSettings originalSettings = ChannelPoolSettings.builder().build();
44+
45+
// 2. Act
46+
BigtableChannelPoolSettings copiedSettings =
47+
ChannelPoolSettingsCopier.toBigtableChannelPoolSettings(originalSettings);
48+
49+
// 3. Assert
50+
assertSettingsCopiedCorrectly(originalSettings, copiedSettings);
51+
}
52+
53+
@Test
54+
public void testToBigtableChannelPoolSettingsNullInputReturnsNull() {
55+
ChannelPoolSettings originalSettings = null;
56+
BigtableChannelPoolSettings copiedSettings =
57+
ChannelPoolSettingsCopier.toBigtableChannelPoolSettings(originalSettings);
58+
assertThat(copiedSettings).isNull();
59+
}
60+
61+
private void assertSettingsCopiedCorrectly(
62+
ChannelPoolSettings originalSettings, BigtableChannelPoolSettings copiedSettings)
63+
throws Exception {
64+
Class<ChannelPoolSettings> originalSettingsClass = ChannelPoolSettings.class;
65+
66+
// Get all public abstract methods from ChannelPoolSettings that start with "get" or "is"
67+
// and exclude methods from Object.class
68+
List<Method> originalPoolGetters = Arrays.stream(ChannelPoolSettings.class.getMethods())
69+
.filter(method -> Modifier.isPublic(method.getModifiers())
70+
&& Modifier.isAbstract(method.getModifiers())
71+
&& (method.getName().startsWith("get") || method.getName().startsWith("is"))
72+
&& method.getDeclaringClass() != Object.class) // Filter out java.lang.Object.getClass()
73+
.collect(Collectors.toList());
74+
75+
for (Method getterMethod : originalPoolGetters) {
76+
try {
77+
Object originalValue = getterMethod.invoke(originalSettings);
78+
Method correspondingMethod = BigtableChannelPoolSettings.class.getMethod(getterMethod.getName());
79+
Object copiedValue = correspondingMethod.invoke(copiedSettings);
80+
81+
assertThat(copiedValue).isEqualTo(originalValue);
82+
} catch (ReflectiveOperationException e) {
83+
throw new AssertionError(
84+
String.format("Reflection error accessing method '%s': %s", getterMethod.getName(), e.getMessage()), e);
85+
} catch (Exception e) { // Catch any other unexpected exceptions
86+
throw new Exception(
87+
String.format("Unexpected error during comparison for method '%s': %s", getterMethod.getName(), e.getMessage()), e);
88+
}
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)