Explorar o código

Frontend: Restart connectors buttons (#1717)

* restart_all_tasks and restart_failed_tasks

* Add Batch to minimize react-redux rendering in multiple dispatch scenarios for restartTasks Async Action

Co-authored-by: Mgrdich <mgotm13@gmail.com>
Co-authored-by: Mgrdich <46796009+Mgrdich@users.noreply.github.com>
NelyDavtyan %!s(int64=3) %!d(string=hai) anos
pai
achega
09b29ded04

+ 42 - 1
kafka-ui-react-app/src/components/Connect/Details/Actions/Actions.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import { useHistory, useParams } from 'react-router-dom';
-import { ConnectorState } from 'generated-sources';
+import { ConnectorState, ConnectorAction } from 'generated-sources';
 import { ClusterName, ConnectName, ConnectorName } from 'redux/interfaces';
 import {
   clusterConnectConnectorEditPath,
@@ -34,6 +34,12 @@ export interface ActionsProps {
     connectName: ConnectName,
     connectorName: ConnectorName
   ): void;
+  restartTasks(
+    clusterName: ClusterName,
+    connectName: ConnectName,
+    connectorName: ConnectorName,
+    action: ConnectorAction
+  ): void;
   pauseConnector(
     clusterName: ClusterName,
     connectName: ConnectName,
@@ -52,11 +58,13 @@ const Actions: React.FC<ActionsProps> = ({
   isConnectorDeleting,
   connectorStatus,
   restartConnector,
+  restartTasks,
   pauseConnector,
   resumeConnector,
   isConnectorActionRunning,
 }) => {
   const { clusterName, connectName, connectorName } = useParams<RouterParams>();
+
   const history = useHistory();
   const [
     isDeleteConnectorConfirmationVisible,
@@ -76,6 +84,13 @@ const Actions: React.FC<ActionsProps> = ({
     restartConnector(clusterName, connectName, connectorName);
   }, [restartConnector, clusterName, connectName, connectorName]);
 
+  const restartTasksHandler = React.useCallback(
+    (actionType) => {
+      restartTasks(clusterName, connectName, connectorName, actionType);
+    },
+    [restartTasks, clusterName, connectName, connectorName]
+  );
+
   const pauseConnectorHandler = React.useCallback(() => {
     pauseConnector(clusterName, connectName, connectorName);
   }, [pauseConnector, clusterName, connectName, connectorName]);
@@ -128,6 +143,32 @@ const Actions: React.FC<ActionsProps> = ({
         </span>
         <span>Restart Connector</span>
       </Button>
+      <Button
+        buttonSize="M"
+        buttonType="primary"
+        type="button"
+        onClick={() => restartTasksHandler(ConnectorAction.RESTART_ALL_TASKS)}
+        disabled={isConnectorActionRunning}
+      >
+        <span>
+          <i className="fas fa-sync-alt" />
+        </span>
+        <span>Restart All Tasks</span>
+      </Button>
+      <Button
+        buttonSize="M"
+        buttonType="primary"
+        type="button"
+        onClick={() =>
+          restartTasksHandler(ConnectorAction.RESTART_FAILED_TASKS)
+        }
+        disabled={isConnectorActionRunning}
+      >
+        <span>
+          <i className="fas fa-sync-alt" />
+        </span>
+        <span>Restart Failed Tasks</span>
+      </Button>
       <Button
         buttonSize="M"
         buttonType="primary"

+ 2 - 0
kafka-ui-react-app/src/components/Connect/Details/Actions/ActionsContainer.ts

@@ -4,6 +4,7 @@ import { RootState } from 'redux/interfaces';
 import {
   deleteConnector,
   restartConnector,
+  restartTasks,
   pauseConnector,
   resumeConnector,
 } from 'redux/actions';
@@ -24,6 +25,7 @@ const mapStateToProps = (state: RootState) => ({
 const mapDispatchToProps = {
   deleteConnector,
   restartConnector,
+  restartTasks,
   pauseConnector,
   resumeConnector,
 };

+ 1 - 0
kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/Actions.spec.tsx

@@ -50,6 +50,7 @@ describe('Actions', () => {
             isConnectorDeleting={false}
             connectorStatus={ConnectorState.RUNNING}
             restartConnector={jest.fn()}
+            restartTasks={jest.fn()}
             pauseConnector={jest.fn()}
             resumeConnector={jest.fn()}
             isConnectorActionRunning={false}

+ 180 - 0
kafka-ui-react-app/src/components/Connect/Details/Actions/__tests__/__snapshots__/Actions.spec.tsx.snap

@@ -144,6 +144,36 @@ exports[`Actions view matches snapshot 1`] = `
       Restart Connector
     </span>
   </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart All Tasks
+    </span>
+  </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart Failed Tasks
+    </span>
+  </button>
   <a
     href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
     onClick={[Function]}
@@ -337,6 +367,36 @@ exports[`Actions view matches snapshot when deleting connector 1`] = `
       Restart Connector
     </span>
   </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart All Tasks
+    </span>
+  </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart Failed Tasks
+    </span>
+  </button>
   <a
     href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
     onClick={[Function]}
@@ -515,6 +575,36 @@ exports[`Actions view matches snapshot when failed 1`] = `
       Restart Connector
     </span>
   </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart All Tasks
+    </span>
+  </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart Failed Tasks
+    </span>
+  </button>
   <a
     href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
     onClick={[Function]}
@@ -708,6 +798,36 @@ exports[`Actions view matches snapshot when paused 1`] = `
       Restart Connector
     </span>
   </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart All Tasks
+    </span>
+  </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart Failed Tasks
+    </span>
+  </button>
   <a
     href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
     onClick={[Function]}
@@ -901,6 +1021,36 @@ exports[`Actions view matches snapshot when running connector action 1`] = `
       Restart Connector
     </span>
   </button>
+  <button
+    className="c1"
+    disabled={true}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart All Tasks
+    </span>
+  </button>
+  <button
+    className="c1"
+    disabled={true}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart Failed Tasks
+    </span>
+  </button>
   <a
     href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
     onClick={[Function]}
@@ -1079,6 +1229,36 @@ exports[`Actions view matches snapshot when unassigned 1`] = `
       Restart Connector
     </span>
   </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart All Tasks
+    </span>
+  </button>
+  <button
+    className="c1"
+    disabled={false}
+    onClick={[Function]}
+    type="button"
+  >
+    <span>
+      <i
+        className="fas fa-sync-alt"
+      />
+    </span>
+    <span>
+      Restart Failed Tasks
+    </span>
+  </button>
   <a
     href="/ui/clusters/my-cluster/connects/my-connect/connectors/my-connector/edit"
     onClick={[Function]}

+ 1 - 1
kafka-ui-react-app/src/redux/actions/__test__/thunks/connectors.spec.ts

@@ -323,7 +323,7 @@ describe('Thunks', () => {
         actions.restartConnectorAction.failure({
           alert: {
             subject: 'local-first-hdfs-source-connector',
-            title: 'Kafka Connect Connector Tasks Restart',
+            title: 'Kafka Connect Connector Restart',
             response: {
               status: 404,
               statusText: 'Not Found',

+ 6 - 0
kafka-ui-react-app/src/redux/actions/actions.ts

@@ -106,6 +106,12 @@ export const restartConnectorAction = createAsyncAction(
   'RESTART_CONNECTOR__FAILURE'
 )<undefined, undefined, { alert?: FailurePayload }>();
 
+export const restartTasksAction = createAsyncAction(
+  'RESTART_TASKS__REQUEST',
+  'RESTART_TASKS__SUCCESS',
+  'RESTART_TASKS__FAILURE'
+)<undefined, undefined, { alert?: FailurePayload }>();
+
 export const pauseConnectorAction = createAsyncAction(
   'PAUSE_CONNECTOR__REQUEST',
   'PAUSE_CONNECTOR__SUCCESS',

+ 35 - 1
kafka-ui-react-app/src/redux/actions/thunks/connectors.ts

@@ -18,6 +18,7 @@ import {
 } from 'redux/interfaces';
 import * as actions from 'redux/actions';
 import { getResponse } from 'lib/errorHandling';
+import { batch } from 'react-redux';
 
 const apiClientConf = new Configuration(BASE_PARAMS);
 export const kafkaConnectApiClient = new KafkaConnectApi(apiClientConf);
@@ -196,13 +197,46 @@ export const restartConnector =
       const response = await getResponse(error);
       const alert: FailurePayload = {
         subject: [clusterName, connectName, connectorName].join('-'),
-        title: `Kafka Connect Connector Tasks Restart`,
+        title: `Kafka Connect Connector Restart`,
         response,
       };
       dispatch(actions.restartConnectorAction.failure({ alert }));
     }
   };
 
+export const restartTasks =
+  (
+    clusterName: ClusterName,
+    connectName: ConnectName,
+    connectorName: ConnectorName,
+    action: ConnectorAction
+  ): PromiseThunkResult<void> =>
+  async (dispatch) => {
+    dispatch(actions.restartTasksAction.request());
+    try {
+      await kafkaConnectApiClient.updateConnectorState({
+        clusterName,
+        connectName,
+        connectorName,
+        action,
+      });
+      batch(() => {
+        dispatch(actions.restartTasksAction.success());
+        dispatch(
+          fetchConnectorTasks(clusterName, connectName, connectorName, true)
+        );
+      });
+    } catch (error) {
+      const response = await getResponse(error);
+      const alert: FailurePayload = {
+        subject: [clusterName, connectName, connectorName].join('-'),
+        title: `Kafka Connect Connector Tasks Restart`,
+        response,
+      };
+      dispatch(actions.restartTasksAction.failure({ alert }));
+    }
+  };
+
 export const pauseConnector =
   (
     clusterName: ClusterName,