use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.
the class ManagedChannelImplIdlenessTest method oobTransportDoesNotAffectIdleness.
@Test
public void oobTransportDoesNotAffectIdleness() {
// Start a call, which goes to delayed transport
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
// Verify that we have exited the idle mode
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null);
verify(mockLoadBalancerFactory).newLoadBalancer(helperCaptor.capture());
Helper helper = helperCaptor.getValue();
// Fail the RPC
SubchannelPicker failingPicker = mock(SubchannelPicker.class);
when(failingPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withError(Status.UNAVAILABLE));
helper.updatePicker(failingPicker);
executor.runDueTasks();
verify(mockCallListener).onClose(same(Status.UNAVAILABLE), any(Metadata.class));
// ... so that the channel resets its in-use state
assertFalse(channel.inUseStateAggregator.isInUse());
// Now make an RPC on an OOB channel
ManagedChannel oob = helper.createOobChannel(addressGroupList.get(0), "oobauthority");
verify(mockTransportFactory, never()).newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT));
ClientCall<String, Integer> oobCall = oob.newCall(method, CallOptions.DEFAULT);
oobCall.start(mockCallListener2, new Metadata());
verify(mockTransportFactory).newClientTransport(any(SocketAddress.class), same("oobauthority"), same(USER_AGENT));
MockClientTransportInfo oobTransportInfo = newTransports.poll();
assertEquals(0, newTransports.size());
// The OOB transport reports in-use state
oobTransportInfo.listener.transportInUse(true);
// But it won't stop the channel from going idle
verify(mockLoadBalancer, never()).shutdown();
timer.forwardTime(IDLE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
verify(mockLoadBalancer).shutdown();
}
use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.
the class ManagedChannelImplIdlenessTest method realTransportsHoldsOffIdleness.
@Test
public void realTransportsHoldsOffIdleness() throws Exception {
final EquivalentAddressGroup addressGroup = addressGroupList.get(1);
// Start a call, which goes to delayed transport
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
// Verify that we have exited the idle mode
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null);
verify(mockLoadBalancerFactory).newLoadBalancer(helperCaptor.capture());
Helper helper = helperCaptor.getValue();
assertTrue(channel.inUseStateAggregator.isInUse());
// Assume LoadBalancer has received an address, then create a subchannel.
Subchannel subchannel = helper.createSubchannel(addressGroup, Attributes.EMPTY);
subchannel.requestConnection();
MockClientTransportInfo t0 = newTransports.poll();
t0.listener.transportReady();
SubchannelPicker mockPicker = mock(SubchannelPicker.class);
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
helper.updatePicker(mockPicker);
// Delayed transport creates real streams in the app executor
executor.runDueTasks();
// Delayed transport exits in-use, while real transport has not entered in-use yet.
assertFalse(channel.inUseStateAggregator.isInUse());
// Now it's in-use
t0.listener.transportInUse(true);
assertTrue(channel.inUseStateAggregator.isInUse());
// As long as the transport is in-use, the channel won't go idle.
timer.forwardTime(IDLE_TIMEOUT_SECONDS * 2, TimeUnit.SECONDS);
assertTrue(channel.inUseStateAggregator.isInUse());
t0.listener.transportInUse(false);
assertFalse(channel.inUseStateAggregator.isInUse());
// And allow the channel to go idle.
timer.forwardTime(IDLE_TIMEOUT_SECONDS - 1, TimeUnit.SECONDS);
verify(mockLoadBalancer, never()).shutdown();
timer.forwardTime(1, TimeUnit.SECONDS);
verify(mockLoadBalancer).shutdown();
}
use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.
the class DelayedClientTransportTest method reprocess_newStreamRacesWithReprocess.
@Test
public void reprocess_newStreamRacesWithReprocess() throws Exception {
final CyclicBarrier barrier = new CyclicBarrier(2);
// In both phases, we only expect the first pickSubchannel() call to block on the barrier.
final AtomicBoolean nextPickShouldWait = new AtomicBoolean(true);
///////// Phase 1: reprocess() twice with the same picker
SubchannelPicker picker = mock(SubchannelPicker.class);
doAnswer(new Answer<PickResult>() {
@Override
public PickResult answer(InvocationOnMock invocation) throws Throwable {
if (nextPickShouldWait.compareAndSet(true, false)) {
try {
barrier.await();
return PickResult.withNoResult();
} catch (Exception e) {
e.printStackTrace();
}
}
return PickResult.withNoResult();
}
}).when(picker).pickSubchannel(any(PickSubchannelArgs.class));
// Because there is no pending stream yet, it will do nothing but save the picker.
delayedTransport.reprocess(picker);
verify(picker, never()).pickSubchannel(any(PickSubchannelArgs.class));
Thread sideThread = new Thread("sideThread") {
@Override
public void run() {
// Will call pickSubchannel and wait on barrier
delayedTransport.newStream(method, headers, callOptions, statsTraceCtx);
}
};
sideThread.start();
PickSubchannelArgsImpl args = new PickSubchannelArgsImpl(method, headers, callOptions);
PickSubchannelArgsImpl args2 = new PickSubchannelArgsImpl(method, headers2, callOptions);
// Is called from sideThread
verify(picker, timeout(5000)).pickSubchannel(args);
// Because stream has not been buffered (it's still stuck in newStream()), this will do nothing,
// but incrementing the picker version.
delayedTransport.reprocess(picker);
verify(picker).pickSubchannel(args);
// Now let the stuck newStream() through
barrier.await(5, TimeUnit.SECONDS);
sideThread.join(5000);
assertFalse("sideThread should've exited", sideThread.isAlive());
// newStream() detects that there has been a new picker while it's stuck, thus will pick again.
verify(picker, times(2)).pickSubchannel(args);
barrier.reset();
nextPickShouldWait.set(true);
////////// Phase 2: reprocess() with a different picker
// Create the second stream
Thread sideThread2 = new Thread("sideThread2") {
@Override
public void run() {
// Will call pickSubchannel and wait on barrier
delayedTransport.newStream(method, headers2, callOptions, statsTraceCtx);
}
};
sideThread2.start();
// The second stream will see the first picker
verify(picker, timeout(5000)).pickSubchannel(args2);
// While the first stream won't use the first picker any more.
verify(picker, times(2)).pickSubchannel(args);
// Now use a different picker
SubchannelPicker picker2 = mock(SubchannelPicker.class);
when(picker2.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withNoResult());
delayedTransport.reprocess(picker2);
// The pending first stream uses the new picker
verify(picker2).pickSubchannel(args);
// The second stream is still pending in creation, doesn't use the new picker.
verify(picker2, never()).pickSubchannel(args2);
// Now let the second stream finish creation
barrier.await(5, TimeUnit.SECONDS);
sideThread2.join(5000);
assertFalse("sideThread2 should've exited", sideThread2.isAlive());
// The second stream should see the new picker
verify(picker2, timeout(5000)).pickSubchannel(args2);
// Wrapping up
verify(picker, times(2)).pickSubchannel(args);
verify(picker).pickSubchannel(args2);
verify(picker2).pickSubchannel(args);
verify(picker2).pickSubchannel(args);
}
use of io.grpc.LoadBalancer.SubchannelPicker in project grpc-java by grpc.
the class DelayedClientTransportTest method reprocess_NoPendingStream.
@Test
public void reprocess_NoPendingStream() {
SubchannelPicker picker = mock(SubchannelPicker.class);
SubchannelImpl subchannel = mock(SubchannelImpl.class);
when(subchannel.obtainActiveTransport()).thenReturn(mockRealTransport);
when(picker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
when(mockRealTransport.newStream(any(MethodDescriptor.class), any(Metadata.class), any(CallOptions.class), same(statsTraceCtx))).thenReturn(mockRealStream);
delayedTransport.reprocess(picker);
verifyNoMoreInteractions(picker);
verifyNoMoreInteractions(transportListener);
// Though picker was not originally used, it will be saved and serve future streams.
ClientStream stream = delayedTransport.newStream(method, headers, CallOptions.DEFAULT, statsTraceCtx);
verify(picker).pickSubchannel(new PickSubchannelArgsImpl(method, headers, CallOptions.DEFAULT));
verify(subchannel).obtainActiveTransport();
assertSame(mockRealStream, stream);
}
Aggregations