This is an automated email from the ASF dual-hosted git repository.

jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 30f414925c fix(ui): remove redundant api calls in home page (#14295)
30f414925c is described below

commit 30f414925cac88d14f06f65e4a43b1939941472f
Author: Jayesh Choudhary <[email protected]>
AuthorDate: Thu Oct 24 22:39:45 2024 +0530

    fix(ui): remove redundant api calls in home page (#14295)
---
 .../app/components/AsyncInstanceTable.tsx          | 85 +++++++---------------
 .../app/components/Homepage/InstancesTables.tsx    |  8 +-
 .../src/main/resources/app/pages/HomePage.tsx      | 23 ++++--
 .../resources/app/pages/InstanceListingPage.tsx    | 19 ++++-
 .../src/main/resources/app/pages/Tenants.tsx       | 22 +++++-
 .../main/resources/app/utils/PinotMethodUtils.ts   | 32 ++++----
 6 files changed, 101 insertions(+), 88 deletions(-)

diff --git 
a/pinot-controller/src/main/resources/app/components/AsyncInstanceTable.tsx 
b/pinot-controller/src/main/resources/app/components/AsyncInstanceTable.tsx
index 67a0a08841..12d6b94a0c 100644
--- a/pinot-controller/src/main/resources/app/components/AsyncInstanceTable.tsx
+++ b/pinot-controller/src/main/resources/app/components/AsyncInstanceTable.tsx
@@ -19,7 +19,7 @@
 
 import React, { useState, useEffect } from 'react';
 import { get, lowerCase, mapKeys, startCase } from 'lodash';
-import { InstanceType, TableData } from 'Models';
+import { DataTable, InstanceType, TableData } from 'Models';
 import CustomizedTables from './Table';
 import PinotMethodUtils from '../utils/PinotMethodUtils';
 import Utils from '../utils/Utils';
@@ -28,6 +28,8 @@ import Loading from './Loading';
 type BaseProps = {
   instanceType: InstanceType;
   showInstanceDetails?: boolean;
+  instanceNames: string[] | null;
+  liveInstanceNames?: string[];
 };
 
 type ClusterProps = BaseProps & {
@@ -45,7 +47,8 @@ type Props = ClusterProps | TenantProps;
 export const AsyncInstanceTable = ({
   instanceType,
   cluster,
-  tenant,
+  instanceNames,
+  liveInstanceNames,
   showInstanceDetails = false,
 }: Props) => {
   const instanceColumns = showInstanceDetails
@@ -55,68 +58,30 @@ export const AsyncInstanceTable = ({
     Utils.getLoadingTableData(instanceColumns)
   );
 
-  const fetchInstances = async (
-    instanceType: InstanceType,
-    tenant?: string
-  ): Promise<string[]> => {
-    if (tenant) {
-      if (instanceType === InstanceType.BROKER) {
-        return PinotMethodUtils.getBrokerOfTenant(tenant).then(
-          (brokersData) => {
-            return Array.isArray(brokersData) ? brokersData : [];
-          }
-        );
-      } else if (instanceType === InstanceType.SERVER) {
-        return PinotMethodUtils.getServerOfTenant(tenant).then(
-          (serversData) => {
-            return Array.isArray(serversData) ? serversData : [];
-          }
-        );
-      }
-    } else {
-      return fetchInstancesOfType(instanceType);
+  useEffect(() => {
+    if(instanceNames) {
+      const loadingColumns = Array(instanceColumns.length - 1).fill(Loading);
+      setInstanceData({
+        columns: instanceColumns,
+        records: instanceNames.map((name) => [name, ...loadingColumns]) || [],
+      });
     }
-  };
-
-  const fetchInstancesOfType = async (instanceType: InstanceType) => {
-    return PinotMethodUtils.getAllInstances().then((instancesData) => {
-      const lowercaseInstanceData = mapKeys(instancesData, (value, key) =>
-        lowerCase(key)
-      );
-      return get(lowercaseInstanceData, lowerCase(instanceType));
-    });
-  };
+  }, [instanceNames]);
 
   useEffect(() => {
-    const instances = fetchInstances(instanceType, tenant);
-    if (showInstanceDetails && cluster.length > 0) {
-      const instanceDetails = instances.then(async (instancesData) => {
-        const liveInstanceArr = await 
PinotMethodUtils.getLiveInstance(cluster);
-        return PinotMethodUtils.getInstanceData(
-          instancesData,
-          liveInstanceArr.data
-        );
-      });
-      instanceDetails.then((instanceDetailsData) => {
-        setInstanceData(instanceDetailsData);
-      });
-    } else if (showInstanceDetails && cluster.length == 0) {
-      instances.then((instancesData) => {
-        const defaultLoadingArray = Array(4).fill(Loading);
-        setInstanceData({
-          columns: instanceColumns,
-          records:  [[instancesData[0], ...defaultLoadingArray ]],
-        });
-      });
-    } else {
-      instances.then((instancesData) => {
-        setInstanceData({
-          columns: instanceColumns,
-          records: instancesData.map((instance) => [instance]),
-        });
-      });
+    // async load all the other details
+    if(showInstanceDetails && cluster && instanceNames && liveInstanceNames) {
+      fetchAdditionalInstanceDetails();
     }
-  }, [instanceType, cluster, tenant, showInstanceDetails]);
+  }, [showInstanceDetails, cluster, instanceNames, liveInstanceNames]);
+
+  const fetchAdditionalInstanceDetails = async () => {
+    const additionalData = await PinotMethodUtils.getInstanceData(
+      instanceNames,
+      liveInstanceNames
+    );
+    setInstanceData(additionalData);
+  }
 
   return (
     <CustomizedTables
diff --git 
a/pinot-controller/src/main/resources/app/components/Homepage/InstancesTables.tsx
 
b/pinot-controller/src/main/resources/app/components/Homepage/InstancesTables.tsx
index 334dc0d39e..dd5621f447 100644
--- 
a/pinot-controller/src/main/resources/app/components/Homepage/InstancesTables.tsx
+++ 
b/pinot-controller/src/main/resources/app/components/Homepage/InstancesTables.tsx
@@ -20,15 +20,17 @@
 import React from 'react';
 import { startCase } from 'lodash';
 import { AsyncInstanceTable } from '../AsyncInstanceTable';
-import { InstanceType } from 'Models';
+import { DataTable, InstanceType } from 'Models';
 
 type Props = {
   clusterName: string;
   instanceType?: InstanceType;
+  instances: DataTable;
+  liveInstanceNames: string[] | null;
 };
 
 
-const Instances = ({ clusterName, instanceType }: Props) => {
+const Instances = ({ clusterName, instanceType, instances, liveInstanceNames 
}: Props) => {
   const order = [
     InstanceType.CONTROLLER,
     InstanceType.BROKER,
@@ -46,6 +48,8 @@ const Instances = ({ clusterName, instanceType }: Props) => {
               cluster={clusterName}
               instanceType={key}
               showInstanceDetails
+              instanceNames={instances?.[key] || null}
+              liveInstanceNames={liveInstanceNames || null}
             />
           );
         })}
diff --git a/pinot-controller/src/main/resources/app/pages/HomePage.tsx 
b/pinot-controller/src/main/resources/app/pages/HomePage.tsx
index 73f16342cf..e2909b61a8 100644
--- a/pinot-controller/src/main/resources/app/pages/HomePage.tsx
+++ b/pinot-controller/src/main/resources/app/pages/HomePage.tsx
@@ -28,6 +28,7 @@ import ClusterConfig from 
'../components/Homepage/ClusterConfig';
 import useTaskTypesTable from '../components/Homepage/useTaskTypesTable';
 import Skeleton from '@material-ui/lab/Skeleton';
 import { getTenants } from '../requests';
+import { DataTable, InstanceType } from 'Models';
 
 const useStyles = makeStyles((theme) => ({
   paper: {
@@ -82,8 +83,8 @@ const HomePage = () => {
   const [brokerCount, setBrokerCount] = useState(0);
   const [serverCount, setServerCount] = useState(0);
   const [minionCount, setMinionCount] = useState(0);
-  // const [instances, setInstances] = useState<DataTable>();
-
+  const [instances, setInstances] = useState<DataTable>();
+  const [liveInstanceNames, setLiveInstanceNames] = useState<string[]>();
   const [fetchingTables, setFetchingTables] = useState(true);
   const [tablesCount, setTablesCount] = useState(0);
 
@@ -91,10 +92,11 @@ const HomePage = () => {
 
   const fetchData = async () => {
     PinotMethodUtils.getAllInstances().then((res) => {
-      setControllerCount(get(res, 'Controller', []).length);
-      setBrokerCount(get(res, 'Broker', []).length);
-      setServerCount(get(res, 'Server', []).length);
-      setMinionCount(get(res, 'Minion', []).length);
+      setControllerCount(res[InstanceType.CONTROLLER].length);
+      setBrokerCount(res[InstanceType.BROKER].length);
+      setServerCount(res[InstanceType.SERVER].length);
+      setMinionCount(res[InstanceType.MINION].length);
+      setInstances(res);
       setFetchingInstances(false);
     });
 
@@ -114,6 +116,9 @@ const HomePage = () => {
 
     fetchClusterName().then((clusterNameRes) => {
       setClusterName(clusterNameRes);
+      PinotMethodUtils.getLiveInstance(clusterNameRes).then((res) => {
+        setLiveInstanceNames(res.data || []);
+      });
     });
   };
 
@@ -203,7 +208,11 @@ const HomePage = () => {
       </Grid>
       <Box mb={3} />
       <TenantsListing />
-      <Instances clusterName={clusterName} />
+      <Instances 
+        liveInstanceNames={liveInstanceNames} 
+        instances={instances} 
+        clusterName={clusterName} 
+      />
       {taskTypesTable}
       <ClusterConfig />
     </Grid>
diff --git 
a/pinot-controller/src/main/resources/app/pages/InstanceListingPage.tsx 
b/pinot-controller/src/main/resources/app/pages/InstanceListingPage.tsx
index 9d0070725c..770142fdc1 100644
--- a/pinot-controller/src/main/resources/app/pages/InstanceListingPage.tsx
+++ b/pinot-controller/src/main/resources/app/pages/InstanceListingPage.tsx
@@ -19,8 +19,7 @@
 
 import React, {useState, useEffect} from 'react';
 import { Grid, makeStyles } from '@material-ui/core';
-import { startCase, pick } from 'lodash';
-import { DataTable, InstanceType } from 'Models';
+import { DataTable } from 'Models';
 import AppLoader from '../components/AppLoader';
 import PinotMethodUtils from '../utils/PinotMethodUtils';
 import Instances from '../components/Homepage/InstancesTables';
@@ -40,6 +39,8 @@ const InstanceListingPage = () => {
 
   const [fetching, setFetching] = useState(true);
   const [clusterName, setClusterName] = useState('');
+  const [instances, setInstances] = useState<DataTable>();
+  const [liveInstanceNames, setLiveInstanceNames] = useState<string[]>();
 
   const fetchData = async () => {
     let clusterNameRes = localStorage.getItem('pinot_ui:clusterName');
@@ -47,6 +48,13 @@ const InstanceListingPage = () => {
       clusterNameRes = await PinotMethodUtils.getClusterName();
     }
     setClusterName(clusterNameRes);
+
+    const liveInstanceNames = await 
PinotMethodUtils.getLiveInstance(clusterNameRes);
+    setLiveInstanceNames(liveInstanceNames.data || []);
+
+    const instancesList = await PinotMethodUtils.getAllInstances();
+    setInstances(instancesList);
+
     setFetching(false);
   };
 
@@ -60,7 +68,12 @@ const InstanceListingPage = () => {
     <AppLoader />
   ) : (
     <Grid item xs className={classes.gridContainer}>
-      <Instances clusterName={clusterName} instanceType={instanceType} />
+      <Instances 
+        liveInstanceNames={liveInstanceNames} 
+        instances={instances} 
+        clusterName={clusterName} 
+        instanceType={instanceType} 
+      />
     </Grid>
   );
 };
diff --git a/pinot-controller/src/main/resources/app/pages/Tenants.tsx 
b/pinot-controller/src/main/resources/app/pages/Tenants.tsx
index 19f61ec6e1..e43c17c36b 100644
--- a/pinot-controller/src/main/resources/app/pages/Tenants.tsx
+++ b/pinot-controller/src/main/resources/app/pages/Tenants.tsx
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import { Grid, makeStyles } from '@material-ui/core';
 import { InstanceType } from 'Models';
 import { RouteComponentProps } from 'react-router-dom';
@@ -25,6 +25,7 @@ import SimpleAccordion from '../components/SimpleAccordion';
 import AsyncPinotTables from '../components/AsyncPinotTables';
 import CustomButton from '../components/CustomButton';
 import { AsyncInstanceTable } from '../components/AsyncInstanceTable';
+import PinotMethodUtils from '../utils/PinotMethodUtils';
 
 const useStyles = makeStyles((theme) => ({
   operationDiv: {
@@ -41,6 +42,23 @@ type Props = {
 const TenantPage = ({ match }: RouteComponentProps<Props>) => {
   const { tenantName } = match.params;
   const classes = useStyles();
+  const [instanceNames, setInstanceNames] = useState({
+    [InstanceType.BROKER]: null,
+    [InstanceType.SERVER]: null,
+  })
+
+  useEffect(() => {
+     fetchInstanceData();
+  }, []);
+
+  const fetchInstanceData = async () => {
+    const brokerNames = await PinotMethodUtils.getBrokerOfTenant(tenantName) 
|| [];
+    const serverNames = await PinotMethodUtils.getServerOfTenant(tenantName) 
|| [];
+    setInstanceNames({
+      [InstanceType.BROKER]: Array.isArray(brokerNames) ? brokerNames : [],
+      [InstanceType.SERVER]: Array.isArray(serverNames) ? serverNames : [],
+    });
+  }
 
   return (
     <Grid
@@ -83,12 +101,14 @@ const TenantPage = ({ match }: RouteComponentProps<Props>) 
=> {
       <Grid container spacing={2}>
         <Grid item xs={6}>
           <AsyncInstanceTable
+            instanceNames={instanceNames[InstanceType.BROKER]}
             instanceType={InstanceType.BROKER}
             tenant={tenantName}
           />
         </Grid>
         <Grid item xs={6}>
           <AsyncInstanceTable
+            instanceNames={instanceNames[InstanceType.SERVER]}
             instanceType={InstanceType.SERVER}
             tenant={tenantName}
           />
diff --git a/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts 
b/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
index 348751c368..4207e59f47 100644
--- a/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
+++ b/pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
@@ -18,8 +18,8 @@
  */
 
 import jwtDecode from "jwt-decode";
-import { get, map, each, isEqual, isArray, keys, union } from 'lodash';
-import { DataTable, SchemaInfo, SegmentMetadata, SqlException, SQLResult, 
TableSize } from 'Models';
+import { get, each, isEqual, isArray, keys, union } from 'lodash';
+import { DataTable, InstanceType, SchemaInfo, SegmentMetadata, SqlException, 
SQLResult } from 'Models';
 import moment from 'moment';
 import {
   getTenants,
@@ -33,7 +33,6 @@ import {
   getTaskTypes,
   getTaskTypeDebug,
   getTables,
-  getTaskTypeTasks,
   getTaskTypeTasksCount,
   getTaskTypeState,
   stopTasks,
@@ -101,7 +100,7 @@ import {
   getServerToSegmentsCount
 } from '../requests';
 import { baseApi } from './axios-config';
-import Utils, { getDisplaySegmentStatus } from './Utils';
+import Utils from './Utils';
 import { matchPath } from 'react-router';
 import RouterData from '../router';
 const JSONbig = require('json-bigint')({'storeAsString': true})
@@ -147,19 +146,22 @@ const getTenantsData = () => {
 
 // This method is used to fetch all instances on cluster manager home page
 // API: /instances
-// Expected Output: {Controller: ['Controller1', 'Controller2'], Broker: 
['Broker1', 'Broker2']}
+// Expected Output: {CONTROLLER: ['Controller1', 'Controller2'], BROKER: 
['Broker1', 'Broker2']}
 const getAllInstances = () => {
   return getInstances().then(({ data }) => {
-    const initialVal: DataTable = {};
-    // It will create instances list array like
-    // {Controller: ['Controller1', 'Controller2'], Broker: ['Broker1', 
'Broker2']}
-    const groupedData = data.instances.reduce((r, a) => {
-      const y = a.split('_');
-      const key = y[0].trim();
-      r[key] = [...(r[key] || []), a];
-      return r;
-    }, initialVal);
-    return {'Controller': groupedData.Controller, ...groupedData};
+    const instanceTypeToInstancesMap: DataTable = {
+      [InstanceType.CONTROLLER]: [],
+      [InstanceType.BROKER]: [],
+      [InstanceType.SERVER]: [],
+      [InstanceType.MINION]: []
+    };
+    
+    data.instances.forEach((instance) => {
+      const instanceType =  instance.split('_')[0].toUpperCase();
+      instanceTypeToInstancesMap[instanceType].push(instance);
+    });
+
+    return instanceTypeToInstancesMap;
   });
 };
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to