Skip to content

Commit d23206a

Browse files
committed
Fix AbstractManagedChannelImplBuilder#maxInboundMessageSize(int) ABI
As part of refactoring described in issue grpc#7211, the implementation of this method, and its corresponding field was pulled down from internal AbstractManagedChannelImplBuilder to concrete classes that actually enforce this setting. That's the right place for method's implementation, so it wasn't ported to ManagedChannelImplBuilder too. Then AbstractManagedChannelImplBuilder was brought to fix ABI backward compatibility, and temporarily turned into a ForwardingChannelBuilder, see PR grpc#7564. Eventually it will be deleted, after a period with "bridge" solution added in grpc#7834. However, this bringing AbstractManagedChannelImplBuilder back fix unintentionally made this method's ABI backward incompatible: pre-refactoring builds expect maxInboundMessageSize() to be a method of AbstractManagedChannelImplBuilder, and not concrete classes. This problem was caught in grpc#8313. Since the end goal is to keep only this method in concrete classes the need it, to fix its ABI issue, we temporary reintroduce it to the original layer it was removed from, AbstractManagedChannelImplBuilder. This class is also temporary, and its only intention is a ABI compatibility. Once we move forward with dropping ABI compatibility (with grpc#7834), this fix is also no longer necessary, and will go away with AbstractManagedChannelImplBuilder.
1 parent 7cf0578 commit d23206a

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.grpc.internal;
1818

1919
import com.google.common.base.MoreObjects;
20+
import com.google.common.base.Preconditions;
2021
import com.google.errorprone.annotations.DoNotCall;
2122
import io.grpc.BinaryLog;
2223
import io.grpc.ClientInterceptor;
@@ -42,6 +43,14 @@
4243
public abstract class AbstractManagedChannelImplBuilder
4344
<T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {
4445

46+
/**
47+
* Added for ABI compatibility.
48+
*
49+
* <p>See details in {@link #maxInboundMessageSize(int)}.
50+
* TODO(sergiitk): move back to concrete classes as a private field, when this class is removed.
51+
*/
52+
protected int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
53+
4554
/**
4655
* The default constructor.
4756
*/
@@ -161,7 +170,32 @@ public T idleTimeout(long value, TimeUnit unit) {
161170

162171
@Override
163172
public T maxInboundMessageSize(int max) {
164-
delegate().maxInboundMessageSize(max);
173+
/*
174+
Why this method is not delegating, as the rest of the methods?
175+
176+
As part of refactoring described in issue #7211, the implementation of this method,
177+
and its corresponding field was pulled down from internal AbstractManagedChannelImplBuilder
178+
to concrete classes that actually enforce this setting. That's the right place for
179+
method's implementation, so it wasn't ported to ManagedChannelImplBuilder too.
180+
181+
Then AbstractManagedChannelImplBuilder was brought to fix ABI backward compatibility,
182+
and temporarily turned into a ForwardingChannelBuilder, see PR #7564. Eventually it will
183+
be deleted, after a period with "bridge" solution added in #7834.
184+
185+
However, this bringing AbstractManagedChannelImplBuilder back fix unintentionally
186+
made this method's ABI backward incompatible: pre-refactoring builds expect
187+
maxInboundMessageSize() to be a method of AbstractManagedChannelImplBuilder, and not
188+
concrete classes, see https://gist.github.com/sergiitk/39583f20906df1813f5e170317a35dc4#v1322.
189+
This problem was caught in #8313.
190+
191+
Since the end goal is to keep only this method in concrete classes the need it,
192+
to fix its ABI issue, we temporary reintroduce it to the original layer it was removed from,
193+
AbstractManagedChannelImplBuilder. This class is also temporary, and its only intention
194+
is a ABI compatibility. Once we move forward with dropping ABI compatibility (with #7834),
195+
this fix is also no longer necessary, and will go away with AbstractManagedChannelImplBuilder.
196+
*/
197+
Preconditions.checkArgument(max >= 0, "negative max");
198+
maxInboundMessageSize = max;
165199
return thisT();
166200
}
167201

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

+12-2
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
import static org.mockito.Mockito.mock;
2222

2323
import com.google.common.base.Defaults;
24+
import com.google.common.collect.ImmutableSet;
2425
import io.grpc.ForwardingTestUtil;
2526
import io.grpc.ManagedChannel;
2627
import io.grpc.ManagedChannelBuilder;
2728
import java.lang.reflect.Method;
2829
import java.lang.reflect.Modifier;
29-
import java.util.Collections;
3030
import org.junit.Test;
3131
import org.junit.runner.RunWith;
3232
import org.junit.runners.JUnit4;
@@ -53,7 +53,8 @@ public void allMethodsForwarded() throws Exception {
5353
ManagedChannelBuilder.class,
5454
mockDelegate,
5555
testChannelBuilder,
56-
Collections.<Method>emptyList(),
56+
// maxInboundMessageSize is the only method that shouldn't forward.
57+
ImmutableSet.of(ManagedChannelBuilder.class.getMethod("maxInboundMessageSize", int.class)),
5758
new ForwardingTestUtil.ArgumentProvider() {
5859
@Override
5960
public Object get(Method method, int argPos, Class<?> clazz) {
@@ -66,6 +67,15 @@ public Object get(Method method, int argPos, Class<?> clazz) {
6667
});
6768
}
6869

70+
@Test
71+
public void testMaxInboundMessageSize() {
72+
assertThat(testChannelBuilder.maxInboundMessageSize)
73+
.isEqualTo(GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE);
74+
75+
testChannelBuilder.maxInboundMessageSize(42);
76+
assertThat(testChannelBuilder.maxInboundMessageSize).isEqualTo(42);
77+
}
78+
6979
@Test
7080
public void allBuilderMethodsReturnThis() throws Exception {
7181
for (Method method : ManagedChannelBuilder.class.getDeclaredMethods()) {

netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java

-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ public final class NettyChannelBuilder extends
9999
private ObjectPool<? extends EventLoopGroup> eventLoopGroupPool = DEFAULT_EVENT_LOOP_GROUP_POOL;
100100
private boolean autoFlowControl = DEFAULT_AUTO_FLOW_CONTROL;
101101
private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
102-
private int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
103102
private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
104103
private long keepAliveTimeNanos = KEEPALIVE_TIME_NANOS_DISABLED;
105104
private long keepAliveTimeoutNanos = DEFAULT_KEEPALIVE_TIMEOUT_NANOS;

okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java

-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ public static OkHttpChannelBuilder forTarget(String target, ChannelCredentials c
174174
private long keepAliveTimeoutNanos = DEFAULT_KEEPALIVE_TIMEOUT_NANOS;
175175
private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
176176
private boolean keepAliveWithoutCalls;
177-
private int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
178177
private int maxInboundMetadataSize = Integer.MAX_VALUE;
179178

180179
/**

0 commit comments

Comments
 (0)