Search in sources :

Example 16 with SubchannelStateListener

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);
}
Also used : Status(io.grpc.Status) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) InOrder(org.mockito.InOrder) SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) Test(org.junit.Test)

Example 17 with SubchannelStateListener

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);
}
Also used : Status(io.grpc.Status) SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) InOrder(org.mockito.InOrder) SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) PickResult(io.grpc.LoadBalancer.PickResult) Test(org.junit.Test)

Example 18 with SubchannelStateListener

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();
}
Also used : SubchannelPicker(io.grpc.LoadBalancer.SubchannelPicker) SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) Test(org.junit.Test)

Example 19 with SubchannelStateListener

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);
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) InOrder(org.mockito.InOrder) OrcaLoadReport(com.github.xds.data.orca.v3.OrcaLoadReport) Test(org.junit.Test)

Example 20 with SubchannelStateListener

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);
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) InOrder(org.mockito.InOrder) CreateSubchannelArgs(io.grpc.LoadBalancer.CreateSubchannelArgs) Attributes(io.grpc.Attributes) OrcaLoadReport(com.github.xds.data.orca.v3.OrcaLoadReport) Test(org.junit.Test)

Aggregations

SubchannelStateListener (io.grpc.LoadBalancer.SubchannelStateListener)22 Test (org.junit.Test)19 Subchannel (io.grpc.LoadBalancer.Subchannel)13 InOrder (org.mockito.InOrder)13 Attributes (io.grpc.Attributes)11 ResolvedAddresses (io.grpc.LoadBalancer.ResolvedAddresses)7 CreateSubchannelArgs (io.grpc.LoadBalancer.CreateSubchannelArgs)6 Status (io.grpc.Status)6 SubchannelPicker (io.grpc.LoadBalancer.SubchannelPicker)5 OrcaLoadReport (com.github.xds.data.orca.v3.OrcaLoadReport)4 ConnectivityStateInfo (io.grpc.ConnectivityStateInfo)4 MockClientTransportInfo (io.grpc.internal.TestUtils.MockClientTransportInfo)4 ForwardingSubchannel (io.grpc.util.ForwardingSubchannel)4 EquivalentAddressGroup (io.grpc.EquivalentAddressGroup)3 Helper (io.grpc.LoadBalancer.Helper)3 ProxiedSocketAddress (io.grpc.ProxiedSocketAddress)3 ClientTransportOptions (io.grpc.internal.ClientTransportFactory.ClientTransportOptions)3 SocketAddress (java.net.SocketAddress)3 ChannelLogger (io.grpc.ChannelLogger)2 ClientTransportFactoryBuilder (io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder)2