Search in sources :

Example 6 with OrcaLoadReport

use of com.github.xds.data.orca.v3.OrcaLoadReport in project grpc-java by grpc.

the class OrcaOobUtilTest method policiesReceiveSameReportIndependently.

@Test
public void policiesReceiveSameReportIndependently() {
    createSubchannel(childHelperWrapper.asHelper(), 0, Attributes.EMPTY);
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
    // No helper sets ORCA reporting interval, so load reporting is not started.
    verify(mockStateListeners[0]).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
    assertThat(orcaServiceImps[0].calls).isEmpty();
    assertThat(subchannels[0].logs).isEmpty();
    // Parent helper requests ORCA reports with a certain interval, load reporting starts.
    setOrcaReportConfig(parentHelperWrapper, SHORT_INTERVAL_CONFIG);
    assertThat(orcaServiceImps[0].calls).hasSize(1);
    assertLog(subchannels[0].logs, "DEBUG: Starting ORCA reporting for " + subchannels[0].getAllAddresses());
    OrcaLoadReport report = OrcaLoadReport.getDefaultInstance();
    assertThat(orcaServiceImps[0].calls).hasSize(1);
    orcaServiceImps[0].calls.peek().responseObserver.onNext(report);
    assertLog(subchannels[0].logs, "DEBUG: Received an ORCA report: " + report);
    // Only parent helper's listener receives the report.
    ArgumentCaptor<OrcaLoadReport> parentReportCaptor = ArgumentCaptor.forClass(null);
    verify(mockOrcaListener1).onLoadReport(parentReportCaptor.capture());
    assertThat(parentReportCaptor.getValue()).isEqualTo(report);
    verifyNoMoreInteractions(mockOrcaListener2);
    // Now child helper also wants to receive reports.
    setOrcaReportConfig(childHelperWrapper, SHORT_INTERVAL_CONFIG);
    orcaServiceImps[0].calls.peek().responseObserver.onNext(report);
    assertLog(subchannels[0].logs, "DEBUG: Received an ORCA report: " + report);
    // Both helper receives the same report instance.
    ArgumentCaptor<OrcaLoadReport> childReportCaptor = ArgumentCaptor.forClass(null);
    verify(mockOrcaListener1, times(2)).onLoadReport(parentReportCaptor.capture());
    verify(mockOrcaListener2).onLoadReport(childReportCaptor.capture());
    assertThat(childReportCaptor.getValue()).isSameInstanceAs(parentReportCaptor.getValue());
}
Also used : OrcaLoadReport(com.github.xds.data.orca.v3.OrcaLoadReport) Test(org.junit.Test)

Example 7 with OrcaLoadReport

use of com.github.xds.data.orca.v3.OrcaLoadReport 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)

Example 8 with OrcaLoadReport

use of com.github.xds.data.orca.v3.OrcaLoadReport in project grpc-java by grpc.

the class OrcaOobUtilTest method singlePolicyTypicalWorkflow.

@Test
@SuppressWarnings("unchecked")
public void singlePolicyTypicalWorkflow() {
    setOrcaReportConfig(orcaHelperWrapper, SHORT_INTERVAL_CONFIG);
    verify(origHelper, atLeast(0)).getSynchronizationContext();
    verifyNoMoreInteractions(origHelper);
    // Calling createSubchannel() on orcaHelper 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(orcaHelperWrapper.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(mockOrcaListener0);
        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(mockOrcaListener0, 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(mockOrcaListener0);
    }
    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)

Example 9 with OrcaLoadReport

use of com.github.xds.data.orca.v3.OrcaLoadReport in project grpc-java by grpc.

the class OrcaOobUtilTest method orcReportingDisabledWhenServiceNotImplemented.

@Test
@SuppressWarnings("unchecked")
public void orcReportingDisabledWhenServiceNotImplemented() {
    setOrcaReportConfig(orcaHelperWrapper, SHORT_INTERVAL_CONFIG);
    createSubchannel(orcaHelperWrapper.asHelper(), 0, Attributes.EMPTY);
    FakeSubchannel subchannel = subchannels[0];
    OpenRcaServiceImp orcaServiceImp = orcaServiceImps[0];
    SubchannelStateListener mockStateListener = mockStateListeners[0];
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
    verify(mockStateListener).onSubchannelState(eq(ConnectivityStateInfo.forNonError(READY)));
    assertThat(orcaServiceImp.calls).hasSize(1);
    ServerSideCall serverCall = orcaServiceImp.calls.poll();
    assertThat(serverCall.request).isEqualTo(buildOrcaRequestFromConfig(SHORT_INTERVAL_CONFIG));
    subchannel.logs.clear();
    serverCall.responseObserver.onError(Status.UNIMPLEMENTED.asException());
    assertLog(subchannel.logs, "ERROR: OpenRcaService disabled: " + Status.UNIMPLEMENTED);
    verifyNoMoreInteractions(mockOrcaListener0);
    // Re-connecting on Subchannel will reset the "disabled" flag and restart ORCA reporting.
    assertThat(orcaServiceImp.calls).hasSize(0);
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(IDLE));
    deliverSubchannelState(0, ConnectivityStateInfo.forNonError(READY));
    assertLog(subchannel.logs, "DEBUG: Starting ORCA reporting for " + subchannel.getAllAddresses());
    assertThat(orcaServiceImp.calls).hasSize(1);
    serverCall = orcaServiceImp.calls.poll();
    OrcaLoadReport report = OrcaLoadReport.getDefaultInstance();
    serverCall.responseObserver.onNext(report);
    assertLog(subchannel.logs, "DEBUG: Received an ORCA report: " + report);
    verify(mockOrcaListener0).onLoadReport(eq(report));
    verifyNoInteractions(backoffPolicyProvider);
}
Also used : SubchannelStateListener(io.grpc.LoadBalancer.SubchannelStateListener) OrcaLoadReport(com.github.xds.data.orca.v3.OrcaLoadReport) Test(org.junit.Test)

Aggregations

OrcaLoadReport (com.github.xds.data.orca.v3.OrcaLoadReport)9 Test (org.junit.Test)8 SubchannelStateListener (io.grpc.LoadBalancer.SubchannelStateListener)4 Metadata (io.grpc.Metadata)4 InOrder (org.mockito.InOrder)3 Attributes (io.grpc.Attributes)2 ClientStreamTracer (io.grpc.ClientStreamTracer)2 CreateSubchannelArgs (io.grpc.LoadBalancer.CreateSubchannelArgs)2 Context (io.grpc.Context)1 SimpleForwardingServerCall (io.grpc.ForwardingServerCall.SimpleForwardingServerCall)1 Status (io.grpc.Status)1 CallMetricRecorder (io.grpc.services.CallMetricRecorder)1 InternalCallMetricRecorder (io.grpc.services.InternalCallMetricRecorder)1