refactor: list watch trigger
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import { WatchEventType } from '@/config';
|
|
||||||
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import useSetChunkRequest, {
|
import useSetChunkRequest, {
|
||||||
createAxiosToken
|
createAxiosToken
|
||||||
@@ -65,12 +64,6 @@ export default function useTableFetch<T>(
|
|||||||
const axiosTokenRef = useRef<any>(null);
|
const axiosTokenRef = useRef<any>(null);
|
||||||
const timerIDRef = useRef<any>(null);
|
const timerIDRef = useRef<any>(null);
|
||||||
|
|
||||||
// ======= to resolve worker upate issue =======
|
|
||||||
const shouldUpdateRef = useRef(false);
|
|
||||||
const loadendRef = useRef(false);
|
|
||||||
const currentWatchParamsRef = useRef<any>(null);
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
// for skeleton loading
|
// for skeleton loading
|
||||||
const [extraStatus, setExtraStatus] = useState<Record<string, any>>({
|
const [extraStatus, setExtraStatus] = useState<Record<string, any>>({
|
||||||
firstLoad: true
|
firstLoad: true
|
||||||
@@ -97,23 +90,10 @@ export default function useTableFetch<T>(
|
|||||||
...defaultQueryParams
|
...defaultQueryParams
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// for recognize the current watch trigger time, so that we can ignore the previous events
|
||||||
|
const triggerAtRef = useRef<number>(0);
|
||||||
|
|
||||||
const { setChunkRequest } = useSetChunkRequest();
|
const { setChunkRequest } = useSetChunkRequest();
|
||||||
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
|
||||||
events: events,
|
|
||||||
dataList: dataSource.dataList,
|
|
||||||
setDataList(list, opts?: any) {
|
|
||||||
setDataSource((pre) => {
|
|
||||||
return {
|
|
||||||
total: pre.total,
|
|
||||||
totalPage: pre.totalPage,
|
|
||||||
loading: false,
|
|
||||||
loadend: true,
|
|
||||||
dataList: list,
|
|
||||||
deletedIds: opts?.deletedIds || []
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const debounceSetExtraStatus = _.debounce(setExtraStatus, 3000);
|
const debounceSetExtraStatus = _.debounce(setExtraStatus, 3000);
|
||||||
|
|
||||||
@@ -132,16 +112,12 @@ export default function useTableFetch<T>(
|
|||||||
const params = {
|
const params = {
|
||||||
..._.pickBy(query || queryParams, (val: any) => !!val)
|
..._.pickBy(query || queryParams, (val: any) => !!val)
|
||||||
};
|
};
|
||||||
currentWatchParamsRef.current = {
|
chunkRequestRef.current?.current?.cancel?.();
|
||||||
query: { ...params }
|
|
||||||
};
|
|
||||||
axiosTokenRef.current?.cancel?.('CANCEL_PREVIOUS_REQUEST');
|
axiosTokenRef.current?.cancel?.('CANCEL_PREVIOUS_REQUEST');
|
||||||
axiosTokenRef.current = createAxiosToken();
|
axiosTokenRef.current = createAxiosToken();
|
||||||
const res = await fetchAPI(params, {
|
const res = await fetchAPI(params, {
|
||||||
token: axiosTokenRef.current?.token
|
token: axiosTokenRef.current?.token
|
||||||
});
|
});
|
||||||
shouldUpdateRef.current = false;
|
|
||||||
loadendRef.current = true;
|
|
||||||
if (!dataSource.loadend) {
|
if (!dataSource.loadend) {
|
||||||
// add a delay to avoid flash
|
// add a delay to avoid flash
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
@@ -157,9 +133,6 @@ export default function useTableFetch<T>(
|
|||||||
...params,
|
...params,
|
||||||
page: res.pagination.totalPage
|
page: res.pagination.totalPage
|
||||||
};
|
};
|
||||||
currentWatchParamsRef.current = {
|
|
||||||
query: { ...newParams }
|
|
||||||
};
|
|
||||||
const newRes = await fetchAPI(newParams, {
|
const newRes = await fetchAPI(newParams, {
|
||||||
token: axiosTokenRef.current?.token
|
token: axiosTokenRef.current?.token
|
||||||
});
|
});
|
||||||
@@ -177,7 +150,7 @@ export default function useTableFetch<T>(
|
|||||||
if (isInfiniteScroll) {
|
if (isInfiniteScroll) {
|
||||||
setQueryParams(newParams);
|
setQueryParams(newParams);
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDataSource({
|
setDataSource({
|
||||||
@@ -195,6 +168,7 @@ export default function useTableFetch<T>(
|
|||||||
...query
|
...query
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error.message !== 'CANCEL_PREVIOUS_REQUEST') {
|
if (error.message !== 'CANCEL_PREVIOUS_REQUEST') {
|
||||||
setDataSource({
|
setDataSource({
|
||||||
@@ -205,9 +179,7 @@ export default function useTableFetch<T>(
|
|||||||
totalPage: dataSource.totalPage
|
totalPage: dataSource.totalPage
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
loadendRef.current = true;
|
|
||||||
shouldUpdateRef.current = false;
|
|
||||||
} finally {
|
} finally {
|
||||||
debounceSetExtraStatus({
|
debounceSetExtraStatus({
|
||||||
firstLoad: false
|
firstLoad: false
|
||||||
@@ -216,32 +188,46 @@ export default function useTableFetch<T>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const debounceFetchData = _.debounce(
|
const debounceFetchData = _.debounce(() => fetchData(), 300);
|
||||||
(params: any) => fetchData(params, true),
|
|
||||||
300
|
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
||||||
);
|
events: events,
|
||||||
|
dataList: dataSource.dataList,
|
||||||
|
triggerAt: updateManually ? triggerAtRef : undefined,
|
||||||
|
setDataList(list, opts?: any) {
|
||||||
|
setDataSource((pre) => {
|
||||||
|
return {
|
||||||
|
total: pre.total,
|
||||||
|
totalPage: pre.totalPage,
|
||||||
|
loading: false,
|
||||||
|
loadend: true,
|
||||||
|
dataList: list,
|
||||||
|
deletedIds: opts?.deletedIds || []
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onCreate: (newItems: any) => {
|
||||||
|
// ======= to resolve worker update issue =======
|
||||||
|
if (updateManually && triggerAtRef.current && newItems.length > 0) {
|
||||||
|
debounceFetchData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDelete: (newItems: any) => {
|
||||||
|
// ======= to resolve worker update issue =======
|
||||||
|
if (updateManually && triggerAtRef.current && newItems.length > 0) {
|
||||||
|
debounceFetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const updateHandler = (list: any) => {
|
const updateHandler = (list: any) => {
|
||||||
_.each(list, (data: any) => {
|
_.each(list, (data: any) => {
|
||||||
updateChunkedList(data);
|
updateChunkedList(data);
|
||||||
});
|
});
|
||||||
shouldUpdateRef.current = list.some(
|
|
||||||
(data: any) =>
|
|
||||||
data.type === WatchEventType.DELETE ||
|
|
||||||
data.type === WatchEventType.CREATE
|
|
||||||
);
|
|
||||||
|
|
||||||
// ======= to resolve worker upate issue =======
|
|
||||||
// when worker list change (create/delete), fetch data again to update the list
|
|
||||||
if (shouldUpdateRef.current && updateManually && loadendRef.current) {
|
|
||||||
debounceFetchData(currentWatchParamsRef.current || undefined);
|
|
||||||
}
|
|
||||||
// ============================================
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTableListChunkRequest = async (params?: any) => {
|
const createTableListChunkRequest = async (params?: any) => {
|
||||||
if (!API || !watch) return;
|
if (!API || !watch) return;
|
||||||
shouldUpdateRef.current = false;
|
|
||||||
chunkRequestRef.current?.current?.cancel?.();
|
chunkRequestRef.current?.current?.cancel?.();
|
||||||
try {
|
try {
|
||||||
const currentParams = params || queryParams;
|
const currentParams = params || queryParams;
|
||||||
@@ -252,6 +238,7 @@ export default function useTableFetch<T>(
|
|||||||
url: `${API}?${qs.stringify(_.pickBy(query, (val: any) => !!val))}`,
|
url: `${API}?${qs.stringify(_.pickBy(query, (val: any) => !!val))}`,
|
||||||
handler: updateHandler
|
handler: updateHandler
|
||||||
});
|
});
|
||||||
|
triggerAtRef.current = Date.now();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
@@ -282,11 +269,10 @@ export default function useTableFetch<T>(
|
|||||||
paginate?: boolean;
|
paginate?: boolean;
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
loadendRef.current = false;
|
|
||||||
const newQueryParams = { ...queryParams, ...params };
|
const newQueryParams = { ...queryParams, ...params };
|
||||||
setQueryParams(newQueryParams);
|
setQueryParams(newQueryParams);
|
||||||
await fetchData({ query: newQueryParams });
|
const res = await fetchData({ query: newQueryParams });
|
||||||
if (watch && !options?.paginate) {
|
if (watch && !options?.paginate && res) {
|
||||||
createTableListChunkRequest(newQueryParams);
|
createTableListChunkRequest(newQueryParams);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -418,6 +404,7 @@ export default function useTableFetch<T>(
|
|||||||
chunkRequestRef.current?.current?.cancel?.();
|
chunkRequestRef.current?.current?.cancel?.();
|
||||||
axiosTokenRef.current?.cancel?.();
|
axiosTokenRef.current?.cancel?.();
|
||||||
cacheDataListRef.current = [];
|
cacheDataListRef.current = [];
|
||||||
|
triggerAtRef.current = 0;
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -98,8 +98,16 @@ export function useUpdateChunkedList(options: {
|
|||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
if (data?.type === WatchEventType.DELETE && events.includes('DELETE')) {
|
if (data?.type === WatchEventType.DELETE && events.includes('DELETE')) {
|
||||||
|
const deletedList: any[] = [];
|
||||||
|
|
||||||
cacheDataListRef.current = cacheDataListRef.current?.filter(
|
cacheDataListRef.current = cacheDataListRef.current?.filter(
|
||||||
(item: any) => {
|
(item: any) => {
|
||||||
|
// collect deleted items
|
||||||
|
if (triggerAt?.current) {
|
||||||
|
if (ids?.includes(item.id)) {
|
||||||
|
deletedList.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
return !ids?.includes(item.id);
|
return !ids?.includes(item.id);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -107,6 +115,10 @@ export function useUpdateChunkedList(options: {
|
|||||||
options.setDataList?.([...cacheDataListRef.current], {
|
options.setDataList?.([...cacheDataListRef.current], {
|
||||||
deletedIds: [...deletedIdsRef.current]
|
deletedIds: [...deletedIdsRef.current]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('deletedList:', deletedList);
|
||||||
|
|
||||||
|
options.onDelete?.(deletedList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { useIntl } from '@umijs/max';
|
|||||||
import { Button, Input, Space } from 'antd';
|
import { Button, Input, Space } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { profileOptions } from '../../benchmark/config';
|
|
||||||
|
|
||||||
export interface RightActionsProps {
|
export interface RightActionsProps {
|
||||||
handleInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
handleInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
@@ -82,23 +81,6 @@ const RightActions: React.FC<RightActionsProps> = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
></BaseSelect>
|
></BaseSelect>
|
||||||
<BaseSelect
|
|
||||||
allowClear
|
|
||||||
placeholder={intl.formatMessage({
|
|
||||||
id: 'benchmark.table.filter.byProfile'
|
|
||||||
})}
|
|
||||||
style={{ width: 200 }}
|
|
||||||
options={profileOptions.map((item) => ({
|
|
||||||
label: intl.formatMessage({ id: item.label }),
|
|
||||||
value: item.value
|
|
||||||
}))}
|
|
||||||
onChange={(value, option) =>
|
|
||||||
handleQueryChange({
|
|
||||||
profile: value,
|
|
||||||
page: 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
></BaseSelect>
|
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import { ClusterListItem } from '../config/types';
|
|||||||
*
|
*
|
||||||
* @returns loading, fetch, dataList
|
* @returns loading, fetch, dataList
|
||||||
*/
|
*/
|
||||||
export const useQueryClusterList = () => {
|
export const useQueryClusterList = (options?: { useStateData?: boolean }) => {
|
||||||
|
const { useStateData = true } = options || {};
|
||||||
const axiosTokenRef = useRef<CancelTokenSource | null>(null);
|
const axiosTokenRef = useRef<CancelTokenSource | null>(null);
|
||||||
const [dataList, setDataList] = useState<
|
const [dataList, setDataList] = useState<
|
||||||
Array<Partial<ClusterListItem> & { label: string; value: number }>
|
Array<Partial<ClusterListItem> & { label: string; value: number }>
|
||||||
@@ -27,13 +28,15 @@ export const useQueryClusterList = () => {
|
|||||||
const res = await queryClusterList(params, {
|
const res = await queryClusterList(params, {
|
||||||
token: axiosTokenRef.current.token
|
token: axiosTokenRef.current.token
|
||||||
});
|
});
|
||||||
setDataList(
|
if (useStateData) {
|
||||||
res.items?.map((item: ClusterListItem) => ({
|
setDataList(
|
||||||
...item,
|
res.items?.map((item: ClusterListItem) => ({
|
||||||
label: item.name,
|
...item,
|
||||||
value: item.id
|
label: item.name,
|
||||||
})) || []
|
value: item.id
|
||||||
);
|
})) || []
|
||||||
|
);
|
||||||
|
}
|
||||||
return res.items || [];
|
return res.items || [];
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
|||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import NoResult from '@/pages/_components/no-result';
|
import NoResult from '@/pages/_components/no-result';
|
||||||
import PageBox from '@/pages/_components/page-box';
|
import PageBox from '@/pages/_components/page-box';
|
||||||
import { queryClusterList } from '@/pages/cluster-management/apis';
|
import { useQueryClusterList } from '@/pages/cluster-management/services/use-query-cluster-list';
|
||||||
import { useIntl, useSearchParams } from '@umijs/max';
|
import { useIntl, useSearchParams } from '@umijs/max';
|
||||||
import { ConfigProvider, Table } from 'antd';
|
import { ConfigProvider, Table } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -41,11 +41,14 @@ const GPUList: React.FC<{ clusterId?: number; widths?: { input: number } }> = ({
|
|||||||
const [clusterList, setClusterList] = useState<Global.BaseOption<number>[]>(
|
const [clusterList, setClusterList] = useState<Global.BaseOption<number>[]>(
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
const { fetchClusterList } = useQueryClusterList({
|
||||||
|
useStateData: false
|
||||||
|
});
|
||||||
|
|
||||||
const getClusterList = async () => {
|
const getClusterList = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await queryClusterList({ page: -1 });
|
const items = await fetchClusterList({ page: -1 });
|
||||||
const list = res.items?.map((item) => ({
|
const list = items?.map((item) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
value: item.id
|
value: item.id
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import { FilterBar } from '@/components/page-tools';
|
|||||||
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import PageBox from '@/pages/_components/page-box';
|
import PageBox from '@/pages/_components/page-box';
|
||||||
import { queryClusterList } from '@/pages/cluster-management/apis';
|
|
||||||
import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add-worker/config';
|
import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add-worker/config';
|
||||||
import { ClusterListItem } from '@/pages/cluster-management/config/types';
|
import { ClusterListItem } from '@/pages/cluster-management/config/types';
|
||||||
import useAddWorker from '@/pages/cluster-management/hooks/use-add-worker';
|
import useAddWorker from '@/pages/cluster-management/hooks/use-add-worker';
|
||||||
|
import { useQueryClusterList } from '@/pages/cluster-management/services/use-query-cluster-list';
|
||||||
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
|
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
|
||||||
import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
|
import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
@@ -56,6 +56,7 @@ const Workers: React.FC<{
|
|||||||
handleQueryChange,
|
handleQueryChange,
|
||||||
handleNameChange
|
handleNameChange
|
||||||
} = useTableFetch<ListItem>({
|
} = useTableFetch<ListItem>({
|
||||||
|
events: ['UPDATE', 'DELETE', 'CREATE'],
|
||||||
fetchAPI: queryWorkersList,
|
fetchAPI: queryWorkersList,
|
||||||
deleteAPI: deleteWorker,
|
deleteAPI: deleteWorker,
|
||||||
contentForDelete: 'resources.worker',
|
contentForDelete: 'resources.worker',
|
||||||
@@ -71,6 +72,9 @@ const Workers: React.FC<{
|
|||||||
});
|
});
|
||||||
const { MaintenanceModal, handleStopMaintenance, setOpenStatus } =
|
const { MaintenanceModal, handleStopMaintenance, setOpenStatus } =
|
||||||
useWorkerMaintenance({ fetchData: handleSearch });
|
useWorkerMaintenance({ fetchData: handleSearch });
|
||||||
|
const { fetchClusterList } = useQueryClusterList({
|
||||||
|
useStateData: false
|
||||||
|
});
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [updateLabelsData, setUpdateLabelsData] = useState<{
|
const [updateLabelsData, setUpdateLabelsData] = useState<{
|
||||||
@@ -107,15 +111,15 @@ const Workers: React.FC<{
|
|||||||
const params = {
|
const params = {
|
||||||
page: -1
|
page: -1
|
||||||
};
|
};
|
||||||
const res = await queryClusterList(params);
|
const items = await fetchClusterList(params);
|
||||||
const clusterMap = res?.items?.reduce(
|
const clusterMap = items?.reduce(
|
||||||
(acc: Record<number, string>, item: any) => {
|
(acc: Record<number, string>, item: any) => {
|
||||||
acc[item.id] = item.name;
|
acc[item.id] = item.name;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
const list = res?.items?.map((item: any) => ({
|
const list = items?.map((item: any) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
|||||||
Reference in New Issue
Block a user