Skip to content

Commit 0376de1

Browse files
authored
Fix AbstractManagedChannelImplBuilder#maxInboundMessageSize(int) ABI (#8607)
In refactoring described in #7211, the implementation of #maxInboundMessageSize(int) (and its corresponding field) were pulled down from internal AbstractManagedChannelImplBuilder to concrete classes that actually enforce this setting. For the same reason, it wasn't ported to ManagedChannelImplBuilder (the #delegate()). Then AbstractManagedChannelImplBuilder was brought back to fix ABI backward compatibility, and temporarily turned into a ForwardingChannelBuilder, ref PR #7564. Eventually it will be deleted, after a period with "bridge" ABI solution introduced in #7834. However, restoring AbstractManagedChannelImplBuilder unintentionally made ABI of pre-refactoring builds expect it to be a method of AbstractManagedChannelImplBuilder, and not concrete classes, ref #8313. The end goal is to keep #maxInboundMessageSize(int) only in concrete classes that enforce it. To fix method's ABI, we temporary reintroduce it to the original layer it was removed from: AbstractManagedChannelImplBuilder. This class' only intention is to provide short-term ABI compatibility. Once we move forward with dropping the ABI, both fixes are no longer necessary, and both will perish with removing AbstractManagedChannelImplBuilder.
1 parent 9f644a0 commit 0376de1

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

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

+34-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,31 @@ 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+
In refactoring described in #7211, the implementation of #maxInboundMessageSize(int)
177+
(and its corresponding field) was pulled down from internal AbstractManagedChannelImplBuilder
178+
to concrete classes that actually enforce this setting. For the same reason, it wasn't ported
179+
to ManagedChannelImplBuilder (the #delegate()).
180+
181+
Then AbstractManagedChannelImplBuilder was brought back to fix ABI backward compatibility,
182+
and temporarily turned into a ForwardingChannelBuilder, ref PR #7564. Eventually it will
183+
be deleted, after a period with "bridge" ABI solution introduced in #7834.
184+
185+
However, restoring AbstractManagedChannelImplBuilder unintentionally made ABI of
186+
#maxInboundMessageSize(int) implemented by the concrete classes backward incompatible:
187+
pre-refactoring builds expect it to be a method of AbstractManagedChannelImplBuilder,
188+
and not concrete classes, ref #8313.
189+
190+
The end goal is to keep #maxInboundMessageSize(int) only in concrete classes that enforce it.
191+
To fix method's ABI, we temporary reintroduce it to the original layer it was removed from:
192+
AbstractManagedChannelImplBuilder. This class' only intention is to provide short-term
193+
ABI compatibility. Once we move forward with dropping the ABI, both fixes are no longer
194+
necessary, and both will perish with removing AbstractManagedChannelImplBuilder.
195+
*/
196+
Preconditions.checkArgument(max >= 0, "negative max");
197+
maxInboundMessageSize = max;
165198
return thisT();
166199
}
167200

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)