Skip to content

Commit d8398f5

Browse files
committed
expose APIs similar to internalConfigurator
1 parent eab10a9 commit d8398f5

13 files changed

Lines changed: 177 additions & 39 deletions

api/src/main/java/io/grpc/ChildChannelConfigurer.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package io.grpc;
1818

19-
import java.util.function.Consumer;
19+
2020

2121
/**
2222
* A configurer for child channels created by gRPC's internal infrastructure.
@@ -44,27 +44,31 @@
4444
* .build();
4545
* }</pre>
4646
*
47-
* <p>Implementations must be thread-safe as {@link #accept} may be invoked concurrently
47+
* <p>Implementations must be thread-safe as the configure methods may be invoked concurrently
4848
* by multiple internal components.
4949
*
5050
* @since 1.79.0
5151
*/
5252
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/12574")
53-
@FunctionalInterface
54-
public interface ChildChannelConfigurer extends Consumer<ManagedChannelBuilder<?>> {
53+
public interface ChildChannelConfigurer {
5554

5655
/**
5756
* Configures a builder for a new child channel.
5857
*
5958
* <p>This method is invoked synchronously during the creation of the child channel,
6059
* before {@link ManagedChannelBuilder#build()} is called.
6160
*
62-
* <p>Note: The provided {@code builder} is generic (`?`). Implementations should use
63-
* universal configuration methods (like {@code intercept()}, {@code userAgent()}) on the
64-
* builder rather than casting it to specific implementation types.
65-
*
6661
* @param builder the mutable channel builder for the new child channel
6762
*/
68-
@Override
69-
void accept(ManagedChannelBuilder<?> builder);
63+
default void configureChannelBuilder(ManagedChannelBuilder<?> builder) {}
64+
65+
/**
66+
* Configures a builder for a new child server.
67+
*
68+
* <p>This method is invoked synchronously during the creation of the child server,
69+
* before {@link ServerBuilder#build()} is called.
70+
*
71+
* @param builder the mutable server builder for the new child server
72+
*/
73+
default void configureServerBuilder(ServerBuilder<?> builder) {}
7074
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2026 The gRPC Authors
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+
* http://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+
17+
package io.grpc;
18+
19+
import static org.mockito.Mockito.mock;
20+
import static org.mockito.Mockito.verifyNoInteractions;
21+
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.junit.runners.JUnit4;
25+
26+
@RunWith(JUnit4.class)
27+
public class ChildChannelConfigurerTest {
28+
29+
@Test
30+
public void defaultMethods_doNothing() {
31+
ChildChannelConfigurer configurer = new ChildChannelConfigurer() {};
32+
33+
ManagedChannelBuilder<?> mockChannelBuilder = mock(ManagedChannelBuilder.class);
34+
configurer.configureChannelBuilder(mockChannelBuilder);
35+
verifyNoInteractions(mockChannelBuilder);
36+
37+
ServerBuilder<?> mockServerBuilder = mock(ServerBuilder.class);
38+
configurer.configureServerBuilder(mockServerBuilder);
39+
verifyNoInteractions(mockServerBuilder);
40+
}
41+
}

api/src/test/java/io/grpc/NameResolverTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ public void uncaughtException(Thread t, Throwable e) {
147147

148148
// Validate configurer accepts builders
149149
ManagedChannelBuilder<?> mockBuilder = mock(ManagedChannelBuilder.class);
150-
args.getChildChannelConfigurer().accept(mockBuilder);
151-
verify(childChannelConfigurer).accept(mockBuilder);
150+
args.getChildChannelConfigurer().configureChannelBuilder(mockBuilder);
151+
verify(childChannelConfigurer).configureChannelBuilder(mockBuilder);
152152
}
153153

154154
@Test

core/src/main/java/io/grpc/internal/ManagedChannelImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public Result selectConfig(PickSubchannelArgs args) {
155155
private static final LoadBalancer.PickDetailsConsumer NOOP_PICK_DETAILS_CONSUMER =
156156
new LoadBalancer.PickDetailsConsumer() {};
157157

158-
private ChildChannelConfigurer childChannelConfigurer = builder -> {};
158+
private ChildChannelConfigurer childChannelConfigurer = new ChildChannelConfigurer() {};
159159

160160
private final InternalLogId logId;
161161
private final String target;
@@ -1580,7 +1580,9 @@ protected ManagedChannelBuilder<?> delegate() {
15801580

15811581
// Note that we follow the global configurator pattern and try to fuse the configurations as
15821582
// soon as the builder gets created
1583-
builder.childChannelConfigurer(childChannelConfigurer);
1583+
if (childChannelConfigurer != null) {
1584+
childChannelConfigurer.configureChannelBuilder(builder);
1585+
}
15841586

15851587
return builder
15861588
// TODO(zdapeng): executors should not outlive the parent channel.

core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public static ManagedChannelBuilder<?> forTarget(String target) {
125125

126126
private static final Method GET_CLIENT_INTERCEPTOR_METHOD;
127127

128-
ChildChannelConfigurer childChannelConfigurer = builder -> {};
128+
ChildChannelConfigurer childChannelConfigurer = new ChildChannelConfigurer() {};
129129

130130
@Override
131131
public ManagedChannelImplBuilder childChannelConfigurer(

core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -786,11 +786,14 @@ public void childChannelConfigurer_propagatesMetricsAndInterceptors_xdsTarget()
786786
ClientInterceptor mockInterceptor = mock(ClientInterceptor.class);
787787

788788
// Define the Configurer
789-
ChildChannelConfigurer configurer = (builder) -> {
790-
builder.addMetricSink(mockMetricSink);
791-
792-
// Assuming InternalInterceptorFactory is also accessible
793-
builder.interceptWithTarget(target -> mockInterceptor);
789+
ChildChannelConfigurer configurer = new ChildChannelConfigurer() {
790+
@Override
791+
public void configureChannelBuilder(ManagedChannelBuilder<?> builder) {
792+
builder.addMetricSink(mockMetricSink);
793+
794+
// Assuming InternalInterceptorFactory is also accessible
795+
builder.interceptWithTarget(target -> mockInterceptor);
796+
}
794797
};
795798

796799
// Mock NameResolver.Factory to capture Args
@@ -833,7 +836,7 @@ public void childChannelConfigurer_propagatesMetricsAndInterceptors_xdsTarget()
833836
// Stub addMetricSink to return the builder to avoid generic return type issues
834837
doReturn(mockChildBuilder).when(mockChildBuilder).addMetricSink(any());
835838

836-
configurer.accept(mockChildBuilder);
839+
configurer.configureChannelBuilder(mockChildBuilder);
837840
verify(mockChildBuilder).addMetricSink(mockMetricSink);
838841
verify(mockChildBuilder).interceptWithTarget(any());
839842
}

core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
import io.grpc.Channel;
7070
import io.grpc.ChannelCredentials;
7171
import io.grpc.ChannelLogger;
72-
import io.grpc.ChildChannelConfigurer;
7372
import io.grpc.ClientCall;
7473
import io.grpc.ClientInterceptor;
7574
import io.grpc.ClientInterceptors;
@@ -102,7 +101,6 @@
102101
import io.grpc.LoadBalancerRegistry;
103102
import io.grpc.LongCounterMetricInstrument;
104103
import io.grpc.ManagedChannel;
105-
import io.grpc.ManagedChannelBuilder;
106104
import io.grpc.Metadata;
107105
import io.grpc.MethodDescriptor;
108106
import io.grpc.MethodDescriptor.MethodType;
@@ -306,8 +304,6 @@ public String getPolicyName() {
306304
private ArgumentCaptor<ResolvedAddresses> resolvedAddressCaptor;
307305
private ArgumentCaptor<ClientStreamListener> streamListenerCaptor =
308306
ArgumentCaptor.forClass(ClientStreamListener.class);
309-
@Mock
310-
private ChildChannelConfigurer mockChildChannelConfigurer;
311307

312308

313309
private void createChannel(ClientInterceptor... interceptors) {
@@ -3775,6 +3771,7 @@ public void channelsAndSubchannels_oob_instrumented_state() throws Exception {
37753771
assertEquals(SHUTDOWN, getStats(channel).state);
37763772
assertEquals(SHUTDOWN, getStats(oobChannel).state);
37773773
}
3774+
37783775
@Test
37793776
public void binaryLogInstalled() throws Exception {
37803777
final SettableFuture<Boolean> intercepted = SettableFuture.create();

xds/src/main/java/io/grpc/xds/GrpcXdsTransportFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public GrpcXdsTransport(Bootstrapper.ServerInfo serverInfo, CallCredentials call
8888
ManagedChannelBuilder<?> channelBuilder = Grpc.newChannelBuilder(target, channelCredentials)
8989
.keepAliveTime(5, TimeUnit.MINUTES);
9090
if (childChannelConfigurer != null) {
91-
childChannelConfigurer.accept(channelBuilder);
91+
childChannelConfigurer.configureChannelBuilder(channelBuilder);
9292
}
9393
this.channel = channelBuilder.build();
9494
this.callCredentials = callCredentials;

xds/src/main/java/io/grpc/xds/XdsServerBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
5959
private Map<String, ?> bootstrapOverride;
6060
private long drainGraceTime = 10;
6161
private TimeUnit drainGraceTimeUnit = TimeUnit.MINUTES;
62-
private ChildChannelConfigurer childChannelConfigurer = builder -> { };
62+
private ChildChannelConfigurer childChannelConfigurer = new ChildChannelConfigurer() {};
6363

6464
private XdsServerBuilder(NettyServerBuilder nettyDelegate, int port) {
6565
this.delegate = nettyDelegate;

xds/src/main/java/io/grpc/xds/XdsServerWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public void uncaughtException(Thread t, Throwable e) {
129129
// NamedFilterConfig.filterStateKey -> filter_instance.
130130
private final HashMap<String, Filter> activeFiltersDefaultChain = new HashMap<>();
131131

132-
private ChildChannelConfigurer childChannelConfigurer = builder -> { };
132+
private ChildChannelConfigurer childChannelConfigurer = new ChildChannelConfigurer() {};
133133

134134
XdsServerWrapper(
135135
String listenerAddress,

0 commit comments

Comments
 (0)