chore: integrate channel pool fixes (#2599) · googleapis/java-bigtable@a3bb43d · GitHub | Latest TMZ Celebrity News & Gossip | Watch TMZ Live
Skip to content

Commit a3bb43d

Browse files
authored
chore: integrate channel pool fixes (#2599)
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [x] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/java-bigtable/issues/2601) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [x] Code coverage does not decrease (if any source code was changed) - [x] Appropriate docs were updated (if necessary) - [ ] Rollback plan is reviewed and LGTMed - [ ] All new data plane features have a completed end to end testing plan Fixes #2601 ☕️ If you write sample code, please follow the [samples format]( https://togithub.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md).
1 parent 108125b commit a3bb43d

File tree

5 files changed

+288
-9
lines changed

5 files changed

+288
-9
lines changed

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/BigtableClientContext.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
3232
import com.google.cloud.bigtable.data.v2.stub.metrics.ErrorCountPerConnectionMetricTracker;
3333
import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsProvider;
3434
import com.google.cloud.bigtable.data.v2.stub.metrics.NoopMetricsProvider;
35+
import com.google.cloud.bigtable.gaxx.grpc.BigtableTransportChannelProvider;
3536
import io.grpc.ManagedChannelBuilder;
3637
import io.grpc.opentelemetry.GrpcOpenTelemetry;
3738
import io.opentelemetry.api.OpenTelemetry;
@@ -131,7 +132,11 @@ public static BigtableClientContext create(EnhancedBigtableStubSettings settings
131132
builder.getHeaderProvider().getHeaders()));
132133
}
133134

134-
builder.setTransportChannelProvider(transportProvider.build());
135+
BigtableTransportChannelProvider btTransportProvider =
136+
BigtableTransportChannelProvider.create(
137+
(InstantiatingGrpcChannelProvider) transportProvider.build());
138+
139+
builder.setTransportChannelProvider(btTransportProvider);
135140
}
136141

137142
ClientContext clientContext = ClientContext.create(builder.build());

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,13 @@
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
*/
56-
class BigtableChannelPool extends ManagedChannel {
54+
@InternalApi
55+
public class BigtableChannelPool extends ManagedChannel {
5756
@VisibleForTesting
5857
static final Logger LOG = Logger.getLogger(BigtableChannelPool.class.getName());
5958

@@ -68,7 +67,7 @@ class BigtableChannelPool extends ManagedChannel {
6867
private final AtomicInteger indexTicker = new AtomicInteger();
6968
private final String authority;
7069

71-
static BigtableChannelPool create(
70+
public static BigtableChannelPool create(
7271
BigtableChannelPoolSettings settings, ChannelFactory channelFactory) throws IOException {
7372
return new BigtableChannelPool(
7473
settings, channelFactory, Executors.newSingleThreadScheduledExecutor());

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.google.cloud.bigtable.gaxx.grpc;
1717

1818
import com.google.api.core.BetaApi;
19+
import com.google.api.gax.grpc.ChannelPoolSettings;
1920
import com.google.auto.value.AutoValue;
2021
import com.google.common.base.Preconditions;
2122
import java.time.Duration;
@@ -112,6 +113,17 @@ boolean isStaticSize() {
112113

113114
public abstract Builder toBuilder();
114115

116+
public static BigtableChannelPoolSettings copyFrom(ChannelPoolSettings externalSettings) {
117+
return BigtableChannelPoolSettings.builder()
118+
.setMinRpcsPerChannel(externalSettings.getMinRpcsPerChannel())
119+
.setMaxRpcsPerChannel(externalSettings.getMaxRpcsPerChannel())
120+
.setMinChannelCount(externalSettings.getMinChannelCount())
121+
.setMaxChannelCount(externalSettings.getMaxChannelCount())
122+
.setInitialChannelCount(externalSettings.getInitialChannelCount())
123+
.setPreemptiveRefreshEnabled(externalSettings.isPreemptiveRefreshEnabled())
124+
.build();
125+
}
126+
115127
public static BigtableChannelPoolSettings staticallySized(int size) {
116128
return builder()
117129
.setInitialChannelCount(size)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright 2025 Google LLC
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+
package com.google.cloud.bigtable.gaxx.grpc;
17+
18+
import com.google.api.core.InternalApi;
19+
import com.google.api.gax.grpc.ChannelFactory;
20+
import com.google.api.gax.grpc.ChannelPoolSettings;
21+
import com.google.api.gax.grpc.GrpcTransportChannel;
22+
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
23+
import com.google.api.gax.rpc.TransportChannel;
24+
import com.google.api.gax.rpc.TransportChannelProvider;
25+
import com.google.auth.Credentials;
26+
import com.google.common.base.Preconditions;
27+
import io.grpc.ManagedChannel;
28+
import java.io.IOException;
29+
import java.util.Map;
30+
import java.util.concurrent.Executor;
31+
import java.util.concurrent.ScheduledExecutorService;
32+
33+
/**
34+
* An instance of TransportChannelProvider that provides a TransportChannel through a supplied
35+
* InstantiatingGrpcChannelProvider.
36+
*/
37+
@InternalApi
38+
public final class BigtableTransportChannelProvider implements TransportChannelProvider {
39+
40+
private final InstantiatingGrpcChannelProvider delegate;
41+
42+
private BigtableTransportChannelProvider(
43+
InstantiatingGrpcChannelProvider instantiatingGrpcChannelProvider) {
44+
delegate = Preconditions.checkNotNull(instantiatingGrpcChannelProvider);
45+
}
46+
47+
@Override
48+
public boolean shouldAutoClose() {
49+
return delegate.shouldAutoClose();
50+
}
51+
52+
@Override
53+
public boolean needsExecutor() {
54+
return delegate.needsExecutor();
55+
}
56+
57+
@Override
58+
public BigtableTransportChannelProvider withExecutor(ScheduledExecutorService executor) {
59+
return withExecutor((Executor) executor);
60+
}
61+
62+
@Override
63+
public BigtableTransportChannelProvider withExecutor(Executor executor) {
64+
InstantiatingGrpcChannelProvider newChannelProvider =
65+
(InstantiatingGrpcChannelProvider) delegate.withExecutor(executor);
66+
return new BigtableTransportChannelProvider(newChannelProvider);
67+
}
68+
69+
@Override
70+
public boolean needsHeaders() {
71+
return delegate.needsHeaders();
72+
}
73+
74+
@Override
75+
public BigtableTransportChannelProvider withHeaders(Map<String, String> headers) {
76+
InstantiatingGrpcChannelProvider newChannelProvider =
77+
(InstantiatingGrpcChannelProvider) delegate.withHeaders(headers);
78+
return new BigtableTransportChannelProvider(newChannelProvider);
79+
}
80+
81+
@Override
82+
public boolean needsEndpoint() {
83+
return delegate.needsEndpoint();
84+
}
85+
86+
@Override
87+
public TransportChannelProvider withEndpoint(String endpoint) {
88+
InstantiatingGrpcChannelProvider newChannelProvider =
89+
(InstantiatingGrpcChannelProvider) delegate.withEndpoint(endpoint);
90+
return new BigtableTransportChannelProvider(newChannelProvider);
91+
}
92+
93+
@Deprecated
94+
@Override
95+
public boolean acceptsPoolSize() {
96+
return delegate.acceptsPoolSize();
97+
}
98+
99+
@Deprecated
100+
@Override
101+
public TransportChannelProvider withPoolSize(int size) {
102+
InstantiatingGrpcChannelProvider newChannelProvider =
103+
(InstantiatingGrpcChannelProvider) delegate.withPoolSize(size);
104+
return new BigtableTransportChannelProvider(newChannelProvider);
105+
}
106+
107+
/** Expected to only be called once when BigtableClientContext is created */
108+
@Override
109+
public TransportChannel getTransportChannel() throws IOException {
110+
// This provider's main purpose is to replace the default GAX ChannelPool
111+
// with a custom BigtableChannelPool, reusing the delegate's configuration.
112+
113+
// To create our pool, we need a factory for raw gRPC channels.
114+
// We achieve this by configuring our delegate to not use its own pooling
115+
// (by setting pool size to 1) and then calling getTransportChannel() on it.
116+
InstantiatingGrpcChannelProvider singleChannelProvider =
117+
delegate.toBuilder().setChannelPoolSettings(ChannelPoolSettings.staticallySized(1)).build();
118+
119+
ChannelFactory channelFactory =
120+
() -> {
121+
try {
122+
GrpcTransportChannel channel =
123+
(GrpcTransportChannel) singleChannelProvider.getTransportChannel();
124+
return (ManagedChannel) channel.getChannel();
125+
} catch (IOException e) {
126+
throw new java.io.UncheckedIOException(e);
127+
}
128+
};
129+
130+
BigtableChannelPoolSettings btPoolSettings =
131+
BigtableChannelPoolSettings.copyFrom(delegate.getChannelPoolSettings());
132+
133+
BigtableChannelPool btChannelPool = BigtableChannelPool.create(btPoolSettings, channelFactory);
134+
135+
return GrpcTransportChannel.create(btChannelPool);
136+
}
137+
138+
@Override
139+
public String getTransportName() {
140+
return "bigtable";
141+
}
142+
143+
@Override
144+
public boolean needsCredentials() {
145+
return delegate.needsCredentials();
146+
}
147+
148+
@Override
149+
public TransportChannelProvider withCredentials(Credentials credentials) {
150+
InstantiatingGrpcChannelProvider newChannelProvider =
151+
(InstantiatingGrpcChannelProvider) delegate.withCredentials(credentials);
152+
return new BigtableTransportChannelProvider(newChannelProvider);
153+
}
154+
155+
/** Creates a BigtableTransportChannelProvider. */
156+
public static BigtableTransportChannelProvider create(
157+
InstantiatingGrpcChannelProvider instantiatingGrpcChannelProvider) {
158+
return new BigtableTransportChannelProvider(instantiatingGrpcChannelProvider);
159+
}
160+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2025 Google LLC
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+
package com.google.cloud.bigtable.gaxx.grpc;
17+
18+
import static com.google.common.truth.Truth.assertThat;
19+
20+
import com.google.api.gax.grpc.ChannelPoolSettings;
21+
import com.google.common.collect.ImmutableSet;
22+
import java.lang.reflect.Method;
23+
import java.lang.reflect.Modifier;
24+
import java.util.Arrays;
25+
import java.util.Set;
26+
import java.util.stream.Collectors;
27+
import org.junit.Test;
28+
import org.junit.runner.RunWith;
29+
import org.junit.runners.JUnit4;
30+
31+
@RunWith(JUnit4.class)
32+
public class BigtableChannelPoolSettingsTest {
33+
34+
@Test
35+
public void testToBigtableChannelPoolSettingsAllFieldsSetCopiesCorrectly() throws Exception {
36+
ChannelPoolSettings originalSettings =
37+
ChannelPoolSettings.builder()
38+
.setMinRpcsPerChannel(10)
39+
.setMaxRpcsPerChannel(50)
40+
.setMinChannelCount(5)
41+
.setMaxChannelCount(100)
42+
.setInitialChannelCount(20)
43+
.setPreemptiveRefreshEnabled(true)
44+
.build();
45+
46+
BigtableChannelPoolSettings copiedSettings =
47+
BigtableChannelPoolSettings.copyFrom(originalSettings);
48+
assertSettingsCopiedCorrectly(originalSettings, copiedSettings);
49+
}
50+
51+
@Test
52+
public void testToBigtableChannelPoolSettingsDefaultValuesCopiesCorrectly() throws Exception {
53+
ChannelPoolSettings originalSettings = ChannelPoolSettings.builder().build();
54+
BigtableChannelPoolSettings copiedSettings =
55+
BigtableChannelPoolSettings.copyFrom(originalSettings);
56+
assertSettingsCopiedCorrectly(originalSettings, copiedSettings);
57+
}
58+
59+
private void assertSettingsCopiedCorrectly(
60+
ChannelPoolSettings originalSettings, BigtableChannelPoolSettings copiedSettings)
61+
throws Exception {
62+
63+
Set<String> supportedGetters =
64+
ImmutableSet.of(
65+
"getMinRpcsPerChannel",
66+
"getMaxRpcsPerChannel",
67+
"getMinChannelCount",
68+
"getMaxChannelCount",
69+
"getInitialChannelCount",
70+
"isPreemptiveRefreshEnabled",
71+
"isStaticSize");
72+
73+
Set<String> actualGetters =
74+
Arrays.stream(ChannelPoolSettings.class.getDeclaredMethods())
75+
.filter(
76+
method ->
77+
Modifier.isPublic(method.getModifiers())
78+
&& Modifier.isAbstract(method.getModifiers())
79+
&& (method.getName().startsWith("get")
80+
|| method.getName().startsWith("is")))
81+
.map(Method::getName)
82+
.collect(Collectors.toSet());
83+
84+
// If this fails then we need to add support for the additional attributes on the gax
85+
// ChannelPool by updating the BigtableChannelPoolSettings.copyFrom method
86+
assertThat(supportedGetters).containsAtLeastElementsIn(actualGetters);
87+
88+
assertThat(originalSettings.getInitialChannelCount())
89+
.isEqualTo(copiedSettings.getInitialChannelCount());
90+
assertThat(originalSettings.getMaxChannelCount())
91+
.isEqualTo(copiedSettings.getMaxChannelCount());
92+
assertThat(originalSettings.getMinChannelCount())
93+
.isEqualTo(copiedSettings.getMinChannelCount());
94+
assertThat(originalSettings.getMaxRpcsPerChannel())
95+
.isEqualTo(copiedSettings.getMaxRpcsPerChannel());
96+
assertThat(originalSettings.getMinRpcsPerChannel())
97+
.isEqualTo(copiedSettings.getMinRpcsPerChannel());
98+
assertThat(originalSettings.getInitialChannelCount())
99+
.isEqualTo(copiedSettings.getInitialChannelCount());
100+
assertThat(originalSettings.isPreemptiveRefreshEnabled())
101+
.isEqualTo(copiedSettings.isPreemptiveRefreshEnabled());
102+
}
103+
}

0 commit comments

Comments
 (0)

TMZ Celebrity News – Breaking Stories, Videos & Gossip

Looking for the latest TMZ celebrity news? You've come to the right place. From shocking Hollywood scandals to exclusive videos, TMZ delivers it all in real time.

Whether it’s a red carpet slip-up, a viral paparazzi moment, or a legal drama involving your favorite stars, TMZ news is always first to break the story. Stay in the loop with daily updates, insider tips, and jaw-dropping photos.

🎥 Watch TMZ Live

TMZ Live brings you daily celebrity news and interviews straight from the TMZ newsroom. Don’t miss a beat—watch now and see what’s trending in Hollywood.