use of io.grpc.LoadBalancer.SubchannelStateListener in project grpc-java by grpc.
the class PickFirstLoadBalancerTest method refreshNameResolutionAfterSubchannelConnectionBroken.
@Test
public void refreshNameResolutionAfterSubchannelConnectionBroken() {
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(affinity).build());
verify(mockHelper).createSubchannel(any(CreateSubchannelArgs.class));
InOrder inOrder = inOrder(mockHelper, mockSubchannel);
inOrder.verify(mockSubchannel).start(stateListenerCaptor.capture());
SubchannelStateListener stateListener = stateListenerCaptor.getValue();
inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
assertSame(mockSubchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
inOrder.verify(mockSubchannel).requestConnection();
stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(CONNECTING));
inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
assertNull(pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
Status error = Status.UNAUTHENTICATED.withDescription("permission denied");
stateListener.onSubchannelState(ConnectivityStateInfo.forTransientFailure(error));
inOrder.verify(mockHelper).refreshNameResolution();
inOrder.verify(mockHelper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
assertEquals(error, pickerCaptor.getValue().pickSubchannel(mockArgs).getStatus());
stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
assertSame(mockSubchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
// Simulate receiving go-away so the subchannel transit to IDLE.
stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(IDLE));
inOrder.verify(mockHelper).refreshNameResolution();
inOrder.verify(mockHelper).updateBalancingState(eq(IDLE), any(SubchannelPicker.class));
verifyNoMoreInteractions(mockHelper, mockSubchannel);
}
use of io.grpc.LoadBalancer.SubchannelStateListener in project grpc-java by grpc.
the class PickFirstLoadBalancerTest method nameResolutionErrorWithStateChanges.
@Test
public void nameResolutionErrorWithStateChanges() throws Exception {
InOrder inOrder = inOrder(mockHelper);
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(affinity).build());
inOrder.verify(mockHelper).createSubchannel(createArgsCaptor.capture());
verify(mockSubchannel).start(stateListenerCaptor.capture());
CreateSubchannelArgs args = createArgsCaptor.getValue();
assertThat(args.getAddresses()).isEqualTo(servers);
inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), any(SubchannelPicker.class));
SubchannelStateListener stateListener = stateListenerCaptor.getValue();
stateListener.onSubchannelState(ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE));
inOrder.verify(mockHelper).refreshNameResolution();
inOrder.verify(mockHelper).updateBalancingState(eq(TRANSIENT_FAILURE), any(SubchannelPicker.class));
Status error = Status.NOT_FOUND.withDescription("nameResolutionError");
loadBalancer.handleNameResolutionError(error);
inOrder.verify(mockHelper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
assertEquals(null, pickResult.getSubchannel());
assertEquals(error, pickResult.getStatus());
Status error2 = Status.NOT_FOUND.withDescription("nameResolutionError2");
loadBalancer.handleNameResolutionError(error2);
inOrder.verify(mockHelper).updateBalancingState(eq(TRANSIENT_FAILURE), pickerCaptor.capture());
pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
assertEquals(null, pickResult.getSubchannel());
assertEquals(error2, pickResult.getStatus());
verifyNoMoreInteractions(mockHelper);
}
use of io.grpc.LoadBalancer.SubchannelStateListener in project grpc-java by grpc.
the class PickFirstLoadBalancerTest method requestConnection.
@Test
public void requestConnection() {
loadBalancer.requestConnection();
verify(mockSubchannel, never()).requestConnection();
loadBalancer.handleResolvedAddresses(ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(affinity).build());
verify(mockSubchannel).requestConnection();
verify(mockHelper).createSubchannel(createArgsCaptor.capture());
verify(mockSubchannel).start(stateListenerCaptor.capture());
CreateSubchannelArgs args = createArgsCaptor.getValue();
assertThat(args.getAddresses()).isEqualTo(servers);
SubchannelStateListener stateListener = stateListenerCaptor.getValue();
stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(IDLE));
verify(mockHelper).updateBalancingState(eq(IDLE), any(SubchannelPicker.class));
verify(mockSubchannel).requestConnection();
loadBalancer.requestConnection();
verify(mockSubchannel, times(2)).requestConnection();
}
use of io.grpc.LoadBalancer.SubchannelStateListener in project grpc-java by grpc.
the class OrcaOobUtilTest method orcaReportingStreamClosedAndRetried.
@Test
public void orcaReportingStreamClosedAndRetried() {
setOrcaReportConfig(orcaHelperWrapper, SHORT_INTERVAL_CONFIG);
createSubchannel(orcaHelperWrapper.asHelper(), 0, Attributes.EMPTY);
FakeSubchannel subchannel = subchannels[0];
OpenRcaServiceImp orcaServiceImp = orcaServiceImps[0];
SubchannelStateListener mockStateListener = mockStateListeners[0];
InOrder inOrder = inOrder(mockStateListener, mockOrcaListener0, backoffPolicyProvider, backoffPolicy1, backoffPolicy2);
deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
inOrder.verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
assertLog(subchannel.logs, "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
// Server closes the ORCA reporting RPC without any response, will start backoff
// sequence 1 (11ns).
orcaServiceImp.calls.poll().responseObserver.onCompleted();
assertLog(subchannel.logs, "DEBUG: ORCA reporting stream closed with " + Status.OK + ", backoff in 11" + " ns");
inOrder.verify(backoffPolicyProvider).get();
inOrder.verify(backoffPolicy1).nextBackoffNanos();
verifyRetryAfterNanos(inOrder, orcaServiceImp, 11);
assertLog(subchannel.logs, "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
// Server closes the ORCA reporting RPC with an error, will continue backoff sequence 1 (21ns).
orcaServiceImp.calls.poll().responseObserver.onError(Status.UNAVAILABLE.asException());
assertLog(subchannel.logs, "DEBUG: ORCA reporting stream closed with " + Status.UNAVAILABLE + ", backoff in 21" + " ns");
inOrder.verify(backoffPolicy1).nextBackoffNanos();
verifyRetryAfterNanos(inOrder, orcaServiceImp, 21);
assertLog(subchannel.logs, "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
// Server responds normally.
OrcaLoadReport report = OrcaLoadReport.getDefaultInstance();
orcaServiceImp.calls.peek().responseObserver.onNext(report);
assertLog(subchannel.logs, "DEBUG: Received an ORCA report: " + report);
inOrder.verify(mockOrcaListener0).onLoadReport(eq(report));
// Server closes the ORCA reporting RPC after a response, will restart immediately.
orcaServiceImp.calls.poll().responseObserver.onCompleted();
assertThat(subchannel.logs).containsExactly("DEBUG: ORCA reporting stream closed with " + Status.OK + ", backoff in 0" + " ns", "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
subchannel.logs.clear();
// Backoff policy is set to sequence 2 in previous retry.
// Server closes the ORCA reporting RPC with an error, will start backoff sequence 2 (12ns).
orcaServiceImp.calls.poll().responseObserver.onError(Status.UNAVAILABLE.asException());
assertLog(subchannel.logs, "DEBUG: ORCA reporting stream closed with " + Status.UNAVAILABLE + ", backoff in 12" + " ns");
inOrder.verify(backoffPolicyProvider).get();
inOrder.verify(backoffPolicy2).nextBackoffNanos();
verifyRetryAfterNanos(inOrder, orcaServiceImp, 12);
assertLog(subchannel.logs, "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
verifyNoMoreInteractions(mockStateListener, mockOrcaListener0, backoffPolicyProvider, backoffPolicy1, backoffPolicy2);
}
use of io.grpc.LoadBalancer.SubchannelStateListener in project grpc-java by grpc.
the class OrcaOobUtilTest method twoLevelPoliciesTypicalWorkflow.
@Test
public void twoLevelPoliciesTypicalWorkflow() {
setOrcaReportConfig(childHelperWrapper, SHORT_INTERVAL_CONFIG);
setOrcaReportConfig(parentHelperWrapper, SHORT_INTERVAL_CONFIG);
verify(origHelper, atLeast(0)).getSynchronizationContext();
verifyNoMoreInteractions(origHelper);
// Calling createSubchannel() on child helper correctly passes augmented CreateSubchannelArgs
// to origHelper.
ArgumentCaptor<CreateSubchannelArgs> createArgsCaptor = ArgumentCaptor.forClass(null);
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
String subchannelAttrValue = "eag attr " + i;
Attributes attrs = Attributes.newBuilder().set(SUBCHANNEL_ATTR_KEY, subchannelAttrValue).build();
assertThat(unwrap(createSubchannel(childHelperWrapper.asHelper(), i, attrs))).isSameInstanceAs(subchannels[i]);
verify(origHelper, times(i + 1)).createSubchannel(createArgsCaptor.capture());
assertThat(createArgsCaptor.getValue().getAddresses()).isEqualTo(eagLists[i]);
assertThat(createArgsCaptor.getValue().getAttributes().get(SUBCHANNEL_ATTR_KEY)).isEqualTo(subchannelAttrValue);
}
// ORCA reporting does not start until underlying Subchannel is READY.
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
FakeSubchannel subchannel = subchannels[i];
OpenRcaServiceImp orcaServiceImp = orcaServiceImps[i];
SubchannelStateListener mockStateListener = mockStateListeners[i];
InOrder inOrder = inOrder(mockStateListener);
deliverSubchannelState(i, ConnectivityStateInfo.forNonError(IDLE));
deliverSubchannelState(i, ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE));
deliverSubchannelState(i, ConnectivityStateInfo.forNonError(CONNECTING));
inOrder.verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(IDLE)));
inOrder.verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forTransientFailure(Status.UNAVAILABLE)));
inOrder.verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(CONNECTING)));
verifyNoMoreInteractions(mockStateListener);
assertThat(subchannel.logs).isEmpty();
assertThat(orcaServiceImp.calls).isEmpty();
verifyNoMoreInteractions(mockOrcaListener1);
verifyNoMoreInteractions(mockOrcaListener2);
deliverSubchannelState(i, ConnectivityStateInfo.forNonError(READY));
verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
assertThat(orcaServiceImp.calls).hasSize(1);
ServerSideCall serverCall = orcaServiceImp.calls.peek();
assertThat(serverCall.request).isEqualTo(buildOrcaRequestFromConfig(SHORT_INTERVAL_CONFIG));
assertLog(subchannel.logs, "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
// Simulate an ORCA service response. Registered listener will receive an ORCA report for
// each backend.
OrcaLoadReport report = OrcaLoadReport.getDefaultInstance();
serverCall.responseObserver.onNext(report);
assertLog(subchannel.logs, "DEBUG: Received an ORCA report: " + report);
verify(mockOrcaListener1, times(i + 1)).onLoadReport(eq(report));
verify(mockOrcaListener2, times(i + 1)).onLoadReport(eq(report));
}
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
FakeSubchannel subchannel = subchannels[i];
SubchannelStateListener mockStateListener = mockStateListeners[i];
ServerSideCall serverCall = orcaServiceImps[i].calls.peek();
assertThat(serverCall.cancelled).isFalse();
verifyNoMoreInteractions(mockStateListener);
// Shutting down the subchannel will cancel the ORCA reporting RPC.
subchannel.shutdown();
verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(SHUTDOWN)));
assertThat(serverCall.cancelled).isTrue();
assertThat(subchannel.logs).isEmpty();
verifyNoMoreInteractions(mockOrcaListener1, mockOrcaListener2);
}
for (int i = 0; i < NUM_SUBCHANNELS; i++) {
assertThat(orcaServiceImps[i].calls).hasSize(1);
}
verifyNoInteractions(backoffPolicyProvider);
}
Aggregations