Skip to content

Commit

Permalink
fix(ui): remove redundant api calls in home page (apache#14295)
Browse files Browse the repository at this point in the history
  • Loading branch information
jayeshchoudhary authored Oct 24, 2024
1 parent f251f00 commit 30f4149
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -28,6 +28,8 @@ import Loading from './Loading';
type BaseProps = {
instanceType: InstanceType;
showInstanceDetails?: boolean;
instanceNames: string[] | null;
liveInstanceNames?: string[];
};

type ClusterProps = BaseProps & {
Expand All @@ -45,7 +47,8 @@ type Props = ClusterProps | TenantProps;
export const AsyncInstanceTable = ({
instanceType,
cluster,
tenant,
instanceNames,
liveInstanceNames,
showInstanceDetails = false,
}: Props) => {
const instanceColumns = showInstanceDetails
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -46,6 +48,8 @@ const Instances = ({ clusterName, instanceType }: Props) => {
cluster={clusterName}
instanceType={key}
showInstanceDetails
instanceNames={instances?.[key] || null}
liveInstanceNames={liveInstanceNames || null}
/>
);
})}
Expand Down
23 changes: 16 additions & 7 deletions pinot-controller/src/main/resources/app/pages/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -82,19 +83,20 @@ 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);

const { taskTypes, taskTypesTable } = useTaskTypesTable();

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);
});

Expand All @@ -114,6 +116,9 @@ const HomePage = () => {

fetchClusterName().then((clusterNameRes) => {
setClusterName(clusterNameRes);
PinotMethodUtils.getLiveInstance(clusterNameRes).then((res) => {
setLiveInstanceNames(res.data || []);
});
});
};

Expand Down Expand Up @@ -203,7 +208,11 @@ const HomePage = () => {
</Grid>
<Box mb={3} />
<TenantsListing />
<Instances clusterName={clusterName} />
<Instances
liveInstanceNames={liveInstanceNames}
instances={instances}
clusterName={clusterName}
/>
{taskTypesTable}
<ClusterConfig />
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -40,13 +39,22 @@ 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');
if(!clusterNameRes){
clusterNameRes = await PinotMethodUtils.getClusterName();
}
setClusterName(clusterNameRes);

const liveInstanceNames = await PinotMethodUtils.getLiveInstance(clusterNameRes);
setLiveInstanceNames(liveInstanceNames.data || []);

const instancesList = await PinotMethodUtils.getAllInstances();
setInstances(instancesList);

setFetching(false);
};

Expand All @@ -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>
);
};
Expand Down
22 changes: 21 additions & 1 deletion pinot-controller/src/main/resources/app/pages/Tenants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
* 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';
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: {
Expand All @@ -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
Expand Down Expand Up @@ -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}
/>
Expand Down
32 changes: 17 additions & 15 deletions pinot-controller/src/main/resources/app/utils/PinotMethodUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -33,7 +33,6 @@ import {
getTaskTypes,
getTaskTypeDebug,
getTables,
getTaskTypeTasks,
getTaskTypeTasksCount,
getTaskTypeState,
stopTasks,
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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;
});
};

Expand Down

0 comments on commit 30f4149

Please sign in to comment.