use of io.grpc.LoadBalancer.Helper in project grpc-java by grpc.
the class ManagedChannelImplTest method noMoreCallbackAfterLoadBalancerShutdown.
@Test
public void noMoreCallbackAfterLoadBalancerShutdown() {
FakeNameResolverFactory nameResolverFactory = new FakeNameResolverFactory.Builder(expectedUri).setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress))).build();
channelBuilder.nameResolverFactory(nameResolverFactory);
Status resolutionError = Status.UNAVAILABLE.withDescription("Resolution failed");
createChannel();
FakeNameResolverFactory.FakeNameResolver resolver = nameResolverFactory.resolvers.get(0);
verify(mockLoadBalancerProvider).newLoadBalancer(any(Helper.class));
verify(mockLoadBalancer).handleResolvedAddresses(resolvedAddressCaptor.capture());
assertThat(resolvedAddressCaptor.getValue().getAddresses()).containsExactly(addressGroup);
SubchannelStateListener stateListener1 = mock(SubchannelStateListener.class);
SubchannelStateListener stateListener2 = mock(SubchannelStateListener.class);
Subchannel subchannel1 = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, stateListener1);
Subchannel subchannel2 = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, stateListener2);
requestConnectionSafely(helper, subchannel1);
requestConnectionSafely(helper, subchannel2);
verify(mockTransportFactory, times(2)).newClientTransport(any(SocketAddress.class), any(ClientTransportOptions.class), any(ChannelLogger.class));
MockClientTransportInfo transportInfo1 = transports.poll();
MockClientTransportInfo transportInfo2 = transports.poll();
// LoadBalancer receives all sorts of callbacks
transportInfo1.listener.transportReady();
verify(stateListener1, times(2)).onSubchannelState(stateInfoCaptor.capture());
assertSame(CONNECTING, stateInfoCaptor.getAllValues().get(0).getState());
assertSame(READY, stateInfoCaptor.getAllValues().get(1).getState());
verify(stateListener2).onSubchannelState(stateInfoCaptor.capture());
assertSame(CONNECTING, stateInfoCaptor.getValue().getState());
resolver.listener.onError(resolutionError);
verify(mockLoadBalancer).handleNameResolutionError(resolutionError);
verifyNoMoreInteractions(mockLoadBalancer);
channel.shutdown();
verify(mockLoadBalancer).shutdown();
verifyNoMoreInteractions(stateListener1, stateListener2);
// LoadBalancer will normally shutdown all subchannels
shutdownSafely(helper, subchannel1);
shutdownSafely(helper, subchannel2);
// Since subchannels are shutdown, SubchannelStateListeners will only get SHUTDOWN regardless of
// the transport states.
transportInfo1.listener.transportShutdown(Status.UNAVAILABLE);
transportInfo2.listener.transportReady();
verify(stateListener1).onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN));
verify(stateListener2).onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN));
verifyNoMoreInteractions(stateListener1, stateListener2);
// No more callback should be delivered to LoadBalancer after it's shut down
resolver.listener.onError(resolutionError);
resolver.resolved();
verifyNoMoreInteractions(mockLoadBalancer);
}
use of io.grpc.LoadBalancer.Helper in project grpc-java by grpc.
the class ManagedChannelImplTest method idleMode_resetsDelayedTransportPicker.
@Test
public void idleMode_resetsDelayedTransportPicker() {
ClientStream mockStream = mock(ClientStream.class);
Status pickError = Status.UNAVAILABLE.withDescription("pick result error");
long idleTimeoutMillis = 1000L;
channelBuilder.idleTimeout(idleTimeoutMillis, TimeUnit.MILLISECONDS);
channelBuilder.nameResolverFactory(new FakeNameResolverFactory.Builder(expectedUri).setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress))).build());
createChannel();
assertEquals(IDLE, channel.getState(false));
// This call will be buffered in delayedTransport
ClientCall<String, Integer> call = channel.newCall(method, CallOptions.DEFAULT);
call.start(mockCallListener, new Metadata());
// Move channel into TRANSIENT_FAILURE, which will fail the pending call
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withError(pickError));
updateBalancingStateSafely(helper, TRANSIENT_FAILURE, mockPicker);
assertEquals(TRANSIENT_FAILURE, channel.getState(false));
executor.runDueTasks();
verify(mockCallListener).onClose(same(pickError), any(Metadata.class));
// Move channel to idle
timer.forwardNanos(TimeUnit.MILLISECONDS.toNanos(idleTimeoutMillis));
assertEquals(IDLE, channel.getState(false));
// This call should be buffered, but will move the channel out of idle
ClientCall<String, Integer> call2 = channel.newCall(method, CallOptions.DEFAULT);
call2.start(mockCallListener2, new Metadata());
executor.runDueTasks();
verifyNoMoreInteractions(mockCallListener2);
// Get the helper created on exiting idle
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
verify(mockLoadBalancerProvider, times(2)).newLoadBalancer(helperCaptor.capture());
Helper helper2 = helperCaptor.getValue();
// Establish a connection
Subchannel subchannel = createSubchannelSafely(helper2, addressGroup, Attributes.EMPTY, subchannelStateListener);
requestConnectionSafely(helper, subchannel);
MockClientTransportInfo transportInfo = transports.poll();
ConnectionClientTransport mockTransport = transportInfo.transport;
ManagedClientTransport.Listener transportListener = transportInfo.listener;
when(mockTransport.newStream(same(method), any(Metadata.class), any(CallOptions.class), ArgumentMatchers.<ClientStreamTracer[]>any())).thenReturn(mockStream);
transportListener.transportReady();
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper2, READY, mockPicker);
assertEquals(READY, channel.getState(false));
executor.runDueTasks();
// Verify the buffered call was drained
verify(mockTransport).newStream(same(method), any(Metadata.class), any(CallOptions.class), ArgumentMatchers.<ClientStreamTracer[]>any());
verify(mockStream).start(any(ClientStreamListener.class));
}
use of io.grpc.LoadBalancer.Helper in project grpc-java by grpc.
the class ManagedChannelImplIdlenessTest method realTransportsHoldsOffIdleness.
@Test
public void realTransportsHoldsOffIdleness() throws Exception {
final EquivalentAddressGroup addressGroup = servers.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(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
deliverResolutionResult();
Helper helper = helperCaptor.getValue();
assertTrue(channel.inUseStateAggregator.isInUse());
// Assume LoadBalancer has received an address, then create a subchannel.
Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY);
requestConnectionSafely(helper, subchannel);
MockClientTransportInfo t0 = newTransports.poll();
t0.listener.transportReady();
SubchannelPicker mockPicker = mock(SubchannelPicker.class);
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper, READY, 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.Helper in project grpc-java by grpc.
the class ManagedChannelImplIdlenessTest method enterIdleWhileRealTransportInProgress.
@Test
public void enterIdleWhileRealTransportInProgress() {
final EquivalentAddressGroup addressGroup = servers.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(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
deliverResolutionResult();
Helper helper = helperCaptor.getValue();
// Create a subchannel for the real transport to happen on.
Subchannel subchannel = createSubchannelSafely(helper, addressGroup, Attributes.EMPTY);
requestConnectionSafely(helper, subchannel);
MockClientTransportInfo t0 = newTransports.poll();
t0.listener.transportReady();
SubchannelPicker mockPicker = mock(SubchannelPicker.class);
when(mockPicker.pickSubchannel(any(PickSubchannelArgs.class))).thenReturn(PickResult.withSubchannel(subchannel));
updateBalancingStateSafely(helper, READY, mockPicker);
// Delayed transport creates real streams in the app executor
executor.runDueTasks();
// Move transport to the in-use state
t0.listener.transportInUse(true);
// Now we enter Idle mode while real transport is happening
channel.enterIdle();
// Verify that the name resolver and the load balance were shut down.
verify(mockNameResolver).shutdown();
verify(mockLoadBalancer).shutdown();
// When there are no pending streams, the call to enterIdle() should stick and
// we remain in idle mode. We verify this by making sure that the name resolver
// was not started up more than once (the initial startup).
verify(mockNameResolver, atMostOnce()).start(isA(NameResolver.Listener2.class));
}
use of io.grpc.LoadBalancer.Helper in project grpc-java by grpc.
the class ClusterManagerLoadBalancerProviderTest method parseLoadBalancingConfig_valid.
@Test
public void parseLoadBalancingConfig_valid() throws IOException {
final Object fooConfig = new Object();
LoadBalancerProvider lbProviderFoo = new LoadBalancerProvider() {
@Override
public boolean isAvailable() {
return true;
}
@Override
public int getPriority() {
return 5;
}
@Override
public String getPolicyName() {
return "foo_policy";
}
@Override
public LoadBalancer newLoadBalancer(Helper helper) {
throw new UnsupportedOperationException("Should not be called");
}
@Override
public ConfigOrError parseLoadBalancingPolicyConfig(Map<String, ?> rawLoadBalancingPolicyConfig) {
return ConfigOrError.fromConfig(fooConfig);
}
};
final Object barConfig = new Object();
LoadBalancerProvider lbProviderBar = new LoadBalancerProvider() {
@Override
public boolean isAvailable() {
return true;
}
@Override
public int getPriority() {
return 5;
}
@Override
public String getPolicyName() {
return "bar_policy";
}
@Override
public LoadBalancer newLoadBalancer(Helper helper) {
throw new UnsupportedOperationException("Should not be called");
}
@Override
public ConfigOrError parseLoadBalancingPolicyConfig(Map<String, ?> rawLoadBalancingPolicyConfig) {
return ConfigOrError.fromConfig(barConfig);
}
};
lbRegistry.register(lbProviderFoo);
lbRegistry.register(lbProviderBar);
String clusterManagerConfigJson = "{\n" + " \"childPolicy\": {\n" + " \"child1\": {\n" + " \"lbPolicy\": [\n" + " {\n" + " \"foo_policy\": {" + " \"config_name\": \"config_value\"\n" + " }\n" + " }\n" + " ]\n" + " },\n" + " \"child2\": {\n" + " \"lbPolicy\": [\n" + " {\n" + " \"bar_policy\": {}\n" + " }, {\n" + " \"unsupported\": {}\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}";
@SuppressWarnings("unchecked") Map<String, ?> rawLbConfigMap = (Map<String, ?>) JsonParser.parse(clusterManagerConfigJson);
ConfigOrError configOrError = provider.parseLoadBalancingPolicyConfig(rawLbConfigMap);
assertThat(configOrError.getConfig()).isNotNull();
ClusterManagerConfig config = (ClusterManagerConfig) configOrError.getConfig();
assertThat(config.childPolicies).containsExactly("child1", new PolicySelection(lbProviderFoo, fooConfig), "child2", new PolicySelection(lbProviderBar, barConfig));
}
Aggregations