core: enterIdleMode() exits idle if still in use (#4630)

This commit is contained in:
Eric Gribkoff 2018-07-23 09:45:06 -07:00 committed by GitHub
parent c30e509621
commit 877b1a198f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 0 deletions

View File

@ -395,6 +395,9 @@ final class ManagedChannelImpl extends ManagedChannel implements Instrumented<Ch
.build());
}
channelStateManager.gotoState(IDLE);
if (inUseStateAggregator.isInUse()) {
exitIdleMode();
}
}
// Must be run from channelExecutor

View File

@ -1935,6 +1935,50 @@ public class ManagedChannelImplTest {
assertEquals(IDLE, channel.getState(false));
}
@Test
public void enterIdle_exitsIdleIfDelayedStreamPending() {
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri)
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
.build();
channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel();
// Start a call that will be buffered in delayedTransport
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
// enterIdle() will shut down the name resolver and lb policy used to get a pick for the delayed
// call
channel.enterIdle();
assertEquals(IDLE, channel.getState(false));
// enterIdle() will restart the delayed call by exiting idle. This creates a new helper.
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
verify(mockLoadBalancerFactory, times(2)).newLoadBalancer(helperCaptor.capture());
Helper helper2 = helperCaptor.getValue();
// Establish a connection
Subchannel subchannel = helper2.createSubchannel(addressGroup, Attributes.EMPTY);
subchannel.requestConnection();
ClientStream mockStream = mock(ClientStream.class);
MockClientTransportInfo transportInfo = transports.poll();
ConnectionClientTransport mockTransport = transportInfo.transport;
ManagedClientTransport.Listener transportListener = transportInfo.listener;
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class)))
.thenReturn(mockStream);
transportListener.transportReady();
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class)))
.thenReturn(PickResult.withSubchannel(subchannel));
helper2.updateBalancingState(READY, mockPicker);
assertEquals(READY, channel.getState(false));
// Verify the original call was drained
executor.runDueTasks();
verify(mockTransport).newStream(same(method), any(Metadata.class), any(CallOptions.class));
verify(mockStream).start(any(ClientStreamListener.class));
}
@Test
public void updateBalancingStateDoesUpdatePicker() {
ClientStream mockStream = mock(ClientStream.class);