Skip to content

Commit b3a9b3e

Browse files
committed
Move SubchannelStateListener to Subchannel.start().
Also stop passing Subchannel to SubchannelStateListener. This is part of the bigger change to remove Subchannel from all arguments on the LoadBalancer API, so that wrapping of Subchannel won't cause identity problems. Details in #5676
1 parent 579e2a6 commit b3a9b3e

15 files changed

+492
-329
lines changed

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

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -663,22 +663,19 @@ public boolean equals(Object other) {
663663
/**
664664
* Arguments for {@link Helper#createSubchannel(CreateSubchannelArgs)}.
665665
*
666-
* @since 1.21.0
666+
* @since 1.22.0
667667
*/
668668
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
669669
public static final class CreateSubchannelArgs {
670670
private final List<EquivalentAddressGroup> addrs;
671671
private final Attributes attrs;
672-
private final SubchannelStateListener stateListener;
673672
private final Object[][] customOptions;
674673

675674
private CreateSubchannelArgs(
676-
List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions,
677-
SubchannelStateListener stateListener) {
675+
List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
678676
this.addrs = checkNotNull(addrs, "addresses are not set");
679677
this.attrs = checkNotNull(attrs, "attrs");
680678
this.customOptions = checkNotNull(customOptions, "customOptions");
681-
this.stateListener = checkNotNull(stateListener, "SubchannelStateListener is not set");
682679
}
683680

684681
/**
@@ -711,19 +708,11 @@ public <T> T getOption(Key<T> key) {
711708
return key.defaultValue;
712709
}
713710

714-
/**
715-
* Returns the state listener.
716-
*/
717-
public SubchannelStateListener getStateListener() {
718-
return stateListener;
719-
}
720-
721711
/**
722712
* Returns a builder with the same initial values as this object.
723713
*/
724714
public Builder toBuilder() {
725-
return newBuilder().setAddresses(addrs).setAttributes(attrs).setStateListener(stateListener)
726-
.copyCustomOptions(customOptions);
715+
return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
727716
}
728717

729718
/**
@@ -738,7 +727,6 @@ public String toString() {
738727
return MoreObjects.toStringHelper(this)
739728
.add("addrs", addrs)
740729
.add("attrs", attrs)
741-
.add("listener", stateListener)
742730
.add("customOptions", Arrays.deepToString(customOptions))
743731
.toString();
744732
}
@@ -748,7 +736,6 @@ public static final class Builder {
748736

749737
private List<EquivalentAddressGroup> addrs;
750738
private Attributes attrs = Attributes.EMPTY;
751-
private SubchannelStateListener stateListener;
752739
private Object[][] customOptions = new Object[0][2];
753740

754741
Builder() {
@@ -823,23 +810,11 @@ public Builder setAttributes(Attributes attrs) {
823810
return this;
824811
}
825812

826-
/**
827-
* Receives state changes of the created Subchannel. The listener is called from
828-
* the {@link Helper#getSynchronizationContext Synchronization Context}. It's safe to share
829-
* the listener among multiple Subchannels.
830-
*
831-
* <p>This is a <strong>required</strong> property.
832-
*/
833-
public Builder setStateListener(SubchannelStateListener listener) {
834-
this.stateListener = checkNotNull(listener, "listener");
835-
return this;
836-
}
837-
838813
/**
839814
* Creates a new args object.
840815
*/
841816
public CreateSubchannelArgs build() {
842-
return new CreateSubchannelArgs(addrs, attrs, customOptions, stateListener);
817+
return new CreateSubchannelArgs(addrs, attrs, customOptions);
843818
}
844819
}
845820

@@ -950,15 +925,10 @@ public Subchannel createSubchannel(List<EquivalentAddressGroup> addrs, Attribute
950925
* Subchannel, and can be accessed later through {@link Subchannel#getAttributes
951926
* Subchannel.getAttributes()}.
952927
*
953-
* <p>This method <strong>must be called from the {@link #getSynchronizationContext
954-
* Synchronization Context}</strong>, otherwise it may throw. This is to avoid the race between
955-
* the caller and {@link SubchannelStateListener#onSubchannelState}. See <a
956-
* href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for more discussions.
957-
*
958928
* <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
959929
* Subchannels within {@link #shutdown}.
960930
*
961-
* @since 1.21.0
931+
* @since 1.22.0
962932
*/
963933
public Subchannel createSubchannel(CreateSubchannelArgs args) {
964934
throw new UnsupportedOperationException();
@@ -1154,6 +1124,20 @@ public ChannelLogger getChannelLogger() {
11541124
@ThreadSafe
11551125
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
11561126
public abstract static class Subchannel {
1127+
/**
1128+
* Starts the Subchannel. Can only be called once.
1129+
*
1130+
* <p>This method <strong>must be called from the {@link #getSynchronizationContext
1131+
* Synchronization Context}</strong>, otherwise it may throw. This is to avoid the race between
1132+
* the caller and {@link SubchannelStateListener#onSubchannelState}. See <a
1133+
* href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for more discussions.
1134+
*
1135+
* @param listener receives state updates for this Subchannel.
1136+
*/
1137+
public void start(SubchannelStateListener listener) {
1138+
throw new UnsupportedOperationException("Not implemented");
1139+
}
1140+
11571141
/**
11581142
* Shuts down the Subchannel. After this method is called, this Subchannel should no longer
11591143
* be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
@@ -1164,6 +1148,7 @@ public abstract static class Subchannel {
11641148

11651149
/**
11661150
* Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1151+
* Has no effect if {@link #start} has not been called or {@link #shutdown} has been called.
11671152
*
11681153
* @since 1.2.0
11691154
*/
@@ -1242,13 +1227,12 @@ public ChannelLogger getChannelLogger() {
12421227
}
12431228

12441229
/**
1245-
* Receives state changes for one or more {@link Subchannel}s. All methods are run under {@link
1230+
* Receives state changes for one {@link Subchannel}. All methods are run under {@link
12461231
* Helper#getSynchronizationContext}.
12471232
*
1248-
* @since 1.21.0
1233+
* @since 1.22.0
12491234
*/
12501235
public interface SubchannelStateListener {
1251-
12521236
/**
12531237
* Handles a state change on a Subchannel.
12541238
*
@@ -1266,12 +1250,11 @@ public interface SubchannelStateListener {
12661250
* already terminated, thus there won't be further requests to LoadBalancer. Therefore,
12671251
* SHUTDOWN can be safely ignored.
12681252
*
1269-
* @param subchannel the involved Subchannel
12701253
* @param newState the new state
12711254
*
1272-
* @since 1.21.0
1255+
* @since 1.22.0
12731256
*/
1274-
void onSubchannelState(Subchannel subchannel, ConnectivityStateInfo newState);
1257+
void onSubchannelState(ConnectivityStateInfo newState);
12751258
}
12761259

12771260
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public static <T> void testMethodsForwarded(
9797
try {
9898
method.invoke(verify(mockDelegate), args);
9999
} catch (InvocationTargetException e) {
100-
throw new AssertionError(String.format("Method was not forwarded: %s", method));
100+
throw new RuntimeException(String.format("Method was not forwarded: %s", method), e);
101101
}
102102
}
103103

@@ -126,7 +126,7 @@ public interface ArgumentProvider {
126126
* method once. It is recommended that each invocation returns a distinctive object for the
127127
* same type, in order to verify that arguments are passed by the tested class correctly.
128128
*
129-
* @return a value to be passed as an argument. If {@code null}, {@link Default#defaultValue}
129+
* @return a value to be passed as an argument. If {@code null}, {@link Defaults#defaultValue}
130130
* will be used.
131131
*/
132132
@Nullable Object get(Method method, int argPos, Class<?> clazz);

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ public void helper_createSubchannelList_throws() {
163163
new NoopHelper().createSubchannel(CreateSubchannelArgs.newBuilder()
164164
.setAddresses(eag)
165165
.setAttributes(attrs)
166-
.setStateListener(subchannelStateListener)
167166
.build());
168167
fail("Should throw");
169168
} catch (UnsupportedOperationException e) {
@@ -234,7 +233,6 @@ public void createSubchannelArgs_option_keyOps() {
234233
CreateSubchannelArgs args = CreateSubchannelArgs.newBuilder()
235234
.setAddresses(eag)
236235
.setAttributes(attrs)
237-
.setStateListener(subchannelStateListener)
238236
.build();
239237
assertThat(args.getOption(testKey)).isNull();
240238
assertThat(args.getOption(testWithDefaultKey)).isSameInstanceAs(testValue);
@@ -247,7 +245,6 @@ public void createSubchannelArgs_option_addGet() {
247245
CreateSubchannelArgs args = CreateSubchannelArgs.newBuilder()
248246
.setAddresses(eag)
249247
.setAttributes(attrs)
250-
.setStateListener(subchannelStateListener)
251248
.addOption(testKey, testValue)
252249
.build();
253250
assertThat(args.getOption(testKey)).isEqualTo(testValue);
@@ -261,7 +258,6 @@ public void createSubchannelArgs_option_lastOneWins() {
261258
CreateSubchannelArgs args = CreateSubchannelArgs.newBuilder()
262259
.setAddresses(eag)
263260
.setAttributes(attrs)
264-
.setStateListener(subchannelStateListener)
265261
.addOption(testKey, testValue1)
266262
.addOption(testKey, testValue2)
267263
.build();
@@ -275,13 +271,11 @@ public void createSubchannelArgs_build() {
275271
CreateSubchannelArgs args = CreateSubchannelArgs.newBuilder()
276272
.setAddresses(eag)
277273
.setAttributes(attrs)
278-
.setStateListener(subchannelStateListener)
279274
.addOption(testKey, testValue)
280275
.build();
281276
CreateSubchannelArgs rebuildedArgs = args.toBuilder().build();
282277
assertThat(rebuildedArgs.getAddresses()).containsExactly(eag);
283278
assertThat(rebuildedArgs.getAttributes()).isSameInstanceAs(attrs);
284-
assertThat(rebuildedArgs.getStateListener()).isSameInstanceAs(subchannelStateListener);
285279
assertThat(rebuildedArgs.getOption(testKey)).isSameInstanceAs(testValue);
286280
}
287281

@@ -291,13 +285,11 @@ public void createSubchannelArgs_toString() {
291285
CreateSubchannelArgs args = CreateSubchannelArgs.newBuilder()
292286
.setAddresses(eag)
293287
.setAttributes(attrs)
294-
.setStateListener(subchannelStateListener)
295288
.addOption(testKey, "test-value")
296289
.build();
297290
String str = args.toString();
298291
assertThat(str).contains("addrs=");
299292
assertThat(str).contains("attrs=");
300-
assertThat(str).contains("listener=");
301293
assertThat(str).contains("customOptions=");
302294
}
303295

0 commit comments

Comments
 (0)