Explorar el Código

Added failed connections counter (#1831)

* Added failed connections counter

* Getting failed connectors moved to Redux selector

* Failed connectors test has been rewritten in testing-library way

* Update kafka-ui-react-app/src/components/Connect/List/List.tsx

Co-authored-by: Oleg Shur <workshur@gmail.com>

* Suggestion exepted

* Added test case for failed connectors counter

* Unused import removed

Co-authored-by: k.morozov <k.morozov@ffin.ru>
Co-authored-by: Oleg Shur <workshur@gmail.com>
Kirill Morozov hace 3 años
padre
commit
7eab325ac3

+ 9 - 0
kafka-ui-react-app/src/components/Connect/List/List.tsx

@@ -20,6 +20,7 @@ export interface ListProps {
   areConnectorsFetching: boolean;
   connectors: FullConnectorInfo[];
   connects: Connect[];
+  failedConnectors: FullConnectorInfo[];
   fetchConnects(clusterName: ClusterName): void;
   fetchConnectors({ clusterName }: { clusterName: ClusterName }): void;
   search: string;
@@ -30,6 +31,7 @@ const List: React.FC<ListProps> = ({
   connectors,
   areConnectsFetching,
   areConnectorsFetching,
+  failedConnectors,
   fetchConnects,
   fetchConnectors,
   search,
@@ -72,6 +74,13 @@ const List: React.FC<ListProps> = ({
           >
             {connectors.length}
           </Metrics.Indicator>
+          <Metrics.Indicator
+            label="Failed"
+            title="Failed Connectors"
+            fetching={areConnectsFetching}
+          >
+            {failedConnectors?.length}
+          </Metrics.Indicator>
         </Metrics.Section>
       </Metrics.Wrapper>
       <ControlPanelWrapper hasInput>

+ 2 - 0
kafka-ui-react-app/src/components/Connect/List/ListContainer.ts

@@ -11,6 +11,7 @@ import {
   getAreConnectsFetching,
   getAreConnectorsFetching,
   getConnectorSearch,
+  getFailedConnectors,
 } from 'redux/reducers/connect/selectors';
 import List from 'components/Connect/List/List';
 
@@ -18,6 +19,7 @@ const mapStateToProps = (state: RootState) => ({
   areConnectsFetching: getAreConnectsFetching(state),
   areConnectorsFetching: getAreConnectorsFetching(state),
   connects: getConnects(state),
+  failedConnectors: getFailedConnectors(state),
   connectors: getConnectors(state),
   search: getConnectorSearch(state),
 });

+ 14 - 1
kafka-ui-react-app/src/components/Connect/List/__tests__/List.spec.tsx

@@ -1,5 +1,8 @@
 import React from 'react';
-import { connectors } from 'redux/reducers/connect/__test__/fixtures';
+import {
+  connectors,
+  failedConnectors,
+} from 'redux/reducers/connect/__test__/fixtures';
 import ClusterContext, {
   ContextProps,
   initialValue,
@@ -33,6 +36,7 @@ describe('Connectors List', () => {
             areConnectorsFetching
             areConnectsFetching
             connectors={[]}
+            failedConnectors={[]}
             connects={[]}
             fetchConnects={fetchConnects}
             fetchConnectors={fetchConnectors}
@@ -66,6 +70,15 @@ describe('Connectors List', () => {
       expect(screen.getAllByRole('row').length).toEqual(3);
     });
 
+    it('renders failed connectors list', () => {
+      renderComponent({
+        areConnectorsFetching: false,
+        failedConnectors,
+      });
+      expect(screen.queryByRole('PageLoader')).not.toBeInTheDocument();
+      expect(screen.getByTitle('Failed Connectors')).toBeInTheDocument();
+    });
+
     it('handles fetchConnects and fetchConnectors', () => {
       renderComponent();
       expect(fetchConnects).toHaveBeenCalledTimes(1);

+ 27 - 0
kafka-ui-react-app/src/redux/reducers/connect/__test__/fixtures.ts

@@ -69,6 +69,33 @@ export const connectors: FullConnectorInfo[] = [
   },
 ];
 
+export const failedConnectors: FullConnectorInfo[] = [
+  {
+    connect: 'first',
+    name: 'hdfs-source-connector',
+    connectorClass: 'FileStreamSource',
+    type: ConnectorType.SOURCE,
+    topics: ['test-topic'],
+    status: {
+      state: ConnectorState.FAILED,
+    },
+    tasksCount: 2,
+    failedTasksCount: 0,
+  },
+  {
+    connect: 'second',
+    name: 'hdfs2-source-connector',
+    connectorClass: 'FileStreamSource',
+    type: ConnectorType.SINK,
+    topics: ['test-topic'],
+    status: {
+      state: ConnectorState.FAILED,
+    },
+    tasksCount: 3,
+    failedTasksCount: 1,
+  },
+];
+
 export const connectorServerPayload = {
   connect: 'first',
   name: 'hdfs-source-connector',

+ 9 - 0
kafka-ui-react-app/src/redux/reducers/connect/__test__/selectors.spec.ts

@@ -19,6 +19,7 @@ describe('Connect selectors', () => {
         false
       );
       expect(selectors.getConnectors(store.getState())).toEqual([]);
+      expect(selectors.getFailedConnectors(store.getState())).toEqual([]);
       expect(selectors.getIsConnectorFetching(store.getState())).toEqual(false);
       expect(selectors.getConnector(store.getState())).toEqual(null);
       expect(selectors.getConnectorStatus(store.getState())).toEqual(undefined);
@@ -65,6 +66,14 @@ describe('Connect selectors', () => {
       expect(selectors.getConnectors(store.getState())).toEqual(connectors);
     });
 
+    it('returns failed connectors', () => {
+      store.dispatch({
+        type: fetchConnectors.fulfilled.type,
+        payload: { connectors },
+      });
+      expect(selectors.getFailedConnectors(store.getState()).length).toEqual(1);
+    });
+
     it('returns connector', () => {
       store.dispatch({
         type: fetchConnector.fulfilled.type,

+ 10 - 1
kafka-ui-react-app/src/redux/reducers/connect/selectors.ts

@@ -1,7 +1,7 @@
 import { createSelector } from '@reduxjs/toolkit';
 import { ConnectState, RootState } from 'redux/interfaces';
 import { createFetchingSelector } from 'redux/reducers/loader/selectors';
-import { ConnectorTaskStatus } from 'generated-sources';
+import { ConnectorTaskStatus, ConnectorState } from 'generated-sources';
 
 import {
   deleteConnector,
@@ -43,6 +43,15 @@ export const getConnectors = createSelector(
   ({ connectors }) => connectors
 );
 
+export const getFailedConnectors = createSelector(
+  connectState,
+  ({ connectors }) => {
+    return connectors.filter(
+      (connector) => connector.status.state === ConnectorState.FAILED
+    );
+  }
+);
+
 const getConnectorFetchingStatus = createFetchingSelector(
   fetchConnector.typePrefix
 );