fix: model instances update when tab active

This commit is contained in:
jialin
2025-01-17 23:16:38 +08:00
parent faa13f58e0
commit 1df3a0b8cb
5 changed files with 78 additions and 49 deletions
@@ -1,4 +1,6 @@
import useSetChunkRequest from '@/hooks/use-chunk-request'; import useSetChunkRequest, {
createAxiosToken
} from '@/hooks/use-chunk-request';
import useUpdateChunkedList from '@/hooks/use-update-chunk-list'; import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
import { DownOutlined, RightOutlined } from '@ant-design/icons'; import { DownOutlined, RightOutlined } from '@ant-design/icons';
import { Button, Checkbox, Col, Empty, Row, Spin } from 'antd'; import { Button, Checkbox, Col, Empty, Row, Spin } from 'antd';
@@ -32,6 +34,7 @@ const TableRow: React.FC<
} = props; } = props;
const tableContext: any = React.useContext<{ const tableContext: any = React.useContext<{
allChildren?: any[]; allChildren?: any[];
allSubChildren?: any[];
}>(TableContext); }>(TableContext);
const { setChunkRequest } = useSetChunkRequest(); const { setChunkRequest } = useSetChunkRequest();
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
@@ -43,6 +46,7 @@ const TableRow: React.FC<
const chunkRequestRef = useRef<any>(null); const chunkRequestRef = useRef<any>(null);
const childrenDataRef = useRef<any[]>([]); const childrenDataRef = useRef<any[]>([]);
childrenDataRef.current = childrenData; childrenDataRef.current = childrenData;
const axiosToken = useRef<any>(null);
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({ const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
dataList: childrenData, dataList: childrenData,
@@ -68,6 +72,7 @@ const TableRow: React.FC<
clearInterval(pollTimer.current); clearInterval(pollTimer.current);
} }
chunkRequestRef.current?.current?.cancel?.(); chunkRequestRef.current?.current?.cancel?.();
axiosToken.current?.cancel?.();
}; };
}, []); }, []);
@@ -88,8 +93,12 @@ const TableRow: React.FC<
const handleLoadChildren = async () => { const handleLoadChildren = async () => {
try { try {
axiosToken.current?.cancel?.();
axiosToken.current = createAxiosToken();
setLoading(true); setLoading(true);
const data = await loadChildren?.(record); const data = await loadChildren?.(record, {
token: axiosToken.current?.token
});
setChildrenData(data || []); setChildrenData(data || []);
setLoading(false); setLoading(false);
@@ -144,6 +153,7 @@ const TableRow: React.FC<
} }
if (expanded) { if (expanded) {
axiosToken.current?.cancel?.();
return; return;
} }
@@ -208,6 +218,10 @@ const TableRow: React.FC<
}; };
}, [firstLoad, expanded, tableContext.allChildren]); }, [firstLoad, expanded, tableContext.allChildren]);
useEffect(() => {
console.log('allSubChildren===', tableContext.allSubChildren);
}, [tableContext.allSubChildren]);
const renderRowPrefix = () => { const renderRowPrefix = () => {
if (expandable && rowSelection) { if (expandable && rowSelection) {
return ( return (
+1 -1
View File
@@ -53,7 +53,7 @@ export interface SealTableProps {
onSort?: (dataIndex: string, order: 'ascend' | 'descend') => void; onSort?: (dataIndex: string, order: 'ascend' | 'descend') => void;
onExpand?: (expanded: boolean, record: any, rowKey: any) => void; onExpand?: (expanded: boolean, record: any, rowKey: any) => void;
renderChildren?: (data: any, parent?: any) => React.ReactNode; renderChildren?: (data: any, parent?: any) => React.ReactNode;
loadChildren?: (record: any) => Promise<any[]>; loadChildren?: (record: any, options?: any) => Promise<any[]>;
loadChildrenAPI?: (record: any) => string; loadChildrenAPI?: (record: any) => string;
contentRendered?: () => void; contentRendered?: () => void;
rowKey: string; rowKey: string;
+14 -2
View File
@@ -21,6 +21,16 @@ const setProxyUrl = (url: string) => {
}; };
// ===================== Models ===================== // ===================== Models =====================
export async function queryModelsInstances(options?: any) {
return request<Global.PageResponse<ModelInstanceListItem>>(
MODEL_INSTANCE_API,
{
method: 'GET',
cancelToken: options?.token
}
);
}
export async function queryModelsList( export async function queryModelsList(
params: Global.SearchParams, params: Global.SearchParams,
options?: any options?: any
@@ -69,13 +79,15 @@ export async function queryModelDetail(id: number) {
// ===================== Model Instances start ===================== // ===================== Model Instances start =====================
export async function queryModelInstancesList( export async function queryModelInstancesList(
params: Global.Pagination & { query?: string; id: number } params: Global.Pagination & { query?: string; id: number },
options?: any
) { ) {
return request<Global.PageResponse<ModelInstanceListItem>>( return request<Global.PageResponse<ModelInstanceListItem>>(
`${MODELS_API}/${params.id}/instances`, `${MODELS_API}/${params.id}/instances`,
{ {
method: 'GET', method: 'GET',
params params,
cancelToken: options?.token
} }
); );
} }
+14 -4
View File
@@ -66,6 +66,7 @@ interface ModelsProps {
handleCategoryChange: (val: any) => void; handleCategoryChange: (val: any) => void;
onViewLogs: () => void; onViewLogs: () => void;
onCancelViewLogs: () => void; onCancelViewLogs: () => void;
allInstances: ModelInstanceListItem[];
queryParams: { queryParams: {
page: number; page: number;
perPage: number; perPage: number;
@@ -119,6 +120,7 @@ const Models: React.FC<ModelsProps> = ({
onViewLogs, onViewLogs,
onCancelViewLogs, onCancelViewLogs,
handleCategoryChange, handleCategoryChange,
allInstances,
deleteIds, deleteIds,
dataSource, dataSource,
gpuDeviceList, gpuDeviceList,
@@ -494,13 +496,15 @@ const Models: React.FC<ModelsProps> = ({
[deleteModelInstance] [deleteModelInstance]
); );
const getModelInstances = async (row: any) => { const getModelInstances = async (row: any, options?: any) => {
const params = { const params = {
id: row.id, id: row.id,
page: 1, page: 1,
perPage: 100 perPage: 100
}; };
const data = await queryModelInstancesList(params); const data = await queryModelInstancesList(params, {
token: options?.token
});
return data.items || []; return data.items || [];
}; };
@@ -668,9 +672,15 @@ const Models: React.FC<ModelsProps> = ({
const renderChildren = useCallback( const renderChildren = useCallback(
(list: any, parent?: any) => { (list: any, parent?: any) => {
let childList = list;
if (allInstances.length) {
childList = list.filter((item: any) => {
return allInstances.some((instance) => instance.id === item.id);
});
}
return ( return (
<InstanceItem <InstanceItem
list={list} list={childList}
modelData={parent} modelData={parent}
gpuDeviceList={gpuDeviceList} gpuDeviceList={gpuDeviceList}
workerList={workerList} workerList={workerList}
@@ -678,7 +688,7 @@ const Models: React.FC<ModelsProps> = ({
></InstanceItem> ></InstanceItem>
); );
}, },
[workerList] [workerList, allInstances]
); );
const generateSource = useCallback((record: ListItem) => { const generateSource = useCallback((record: ListItem) => {
+33 -40
View File
@@ -1,5 +1,7 @@
import TableContext from '@/components/seal-table/table-context'; import TableContext from '@/components/seal-table/table-context';
import useSetChunkRequest from '@/hooks/use-chunk-request'; import useSetChunkRequest, {
createAxiosToken as generateAxiosToken
} from '@/hooks/use-chunk-request';
import useUpdateChunkedList from '@/hooks/use-update-chunk-list'; import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
import { queryWorkersList } from '@/pages/resources/apis'; import { queryWorkersList } from '@/pages/resources/apis';
import { import {
@@ -9,10 +11,17 @@ import {
import _ from 'lodash'; import _ from 'lodash';
import qs from 'query-string'; import qs from 'query-string';
import { memo, useCallback, useEffect, useRef, useState } from 'react'; import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { MODELS_API, MODEL_INSTANCE_API, queryModelsList } from './apis'; import {
MODELS_API,
MODEL_INSTANCE_API,
queryModelsInstances,
queryModelsList
} from './apis';
import TableList from './components/table-list'; import TableList from './components/table-list';
import { ListItem } from './config/types'; import { ListItem } from './config/types';
const INSTANCE_SYNC = 'instance_sync';
const Models: React.FC = () => { const Models: React.FC = () => {
const { setChunkRequest, createAxiosToken } = useSetChunkRequest(); const { setChunkRequest, createAxiosToken } = useSetChunkRequest();
const { setChunkRequest: setModelInstanceChunkRequest } = const { setChunkRequest: setModelInstanceChunkRequest } =
@@ -29,13 +38,14 @@ const Models: React.FC = () => {
loading: false, loading: false,
total: 0 total: 0
}); });
const [pageHidden, setPageHidden] = useState(false);
const [allInstances, setAllInstances] = useState<any[]>([]);
const [gpuDeviceList, setGpuDeviceList] = useState<GPUDeviceItem[]>([]); const [gpuDeviceList, setGpuDeviceList] = useState<GPUDeviceItem[]>([]);
const [workerList, setWorkerList] = useState<WokerListItem[]>([]); const [workerList, setWorkerList] = useState<WokerListItem[]>([]);
const [firstLoad, setFirstLoad] = useState(true);
const chunkRequedtRef = useRef<any>(); const chunkRequedtRef = useRef<any>();
const chunkInstanceRequedtRef = useRef<any>(); const chunkInstanceRequedtRef = useRef<any>();
const isPageHidden = useRef(false); const isPageHidden = useRef(false);
const instancesToken = useRef<any>();
let axiosToken = createAxiosToken(); let axiosToken = createAxiosToken();
const [queryParams, setQueryParams] = useState({ const [queryParams, setQueryParams] = useState({
page: 1, page: 1,
@@ -59,6 +69,21 @@ const Models: React.FC = () => {
} }
}); });
const fetchModelsInstances = async () => {
try {
instancesToken.current?.cancel?.();
instancesToken.current = generateAxiosToken();
const data: any = await queryModelsInstances({
token: instancesToken.current?.token
});
console.log('instance====', data);
setAllInstances(data.items || []);
} catch (error) {
// ignore
setAllInstances([]);
}
};
const getWorkerList = async () => { const getWorkerList = async () => {
try { try {
const data = await queryWorkersList({ page: 1, perPage: 100 }); const data = await queryWorkersList({ page: 1, perPage: 100 });
@@ -98,9 +123,6 @@ const Models: React.FC = () => {
deletedIds: [] deletedIds: []
}); });
} }
console.log('error+++', error);
} finally {
setFirstLoad(false);
} }
}, [queryParams]); }, [queryParams]);
@@ -124,7 +146,7 @@ const Models: React.FC = () => {
const updateInstanceHandler = (list: any) => { const updateInstanceHandler = (list: any) => {
setModelInstances(list); setModelInstances(list);
window.postMessage( window.postMessage(
{ type: 'modelInstance', data: list }, { type: INSTANCE_SYNC, data: list },
window.location.origin window.location.origin
); );
}; };
@@ -220,6 +242,7 @@ const Models: React.FC = () => {
chunkRequedtRef.current?.current?.cancel?.(); chunkRequedtRef.current?.current?.cancel?.();
cacheDataListRef.current = []; cacheDataListRef.current = [];
chunkInstanceRequedtRef.current?.current?.cancel?.(); chunkInstanceRequedtRef.current?.current?.cancel?.();
instancesToken.current?.cancel?.();
}; };
}, []); }, []);
@@ -227,6 +250,7 @@ const Models: React.FC = () => {
const handleVisibilityChange = async () => { const handleVisibilityChange = async () => {
if (document.visibilityState === 'visible') { if (document.visibilityState === 'visible') {
isPageHidden.current = false; isPageHidden.current = false;
await fetchModelsInstances();
await Promise.all([ await Promise.all([
createModelsChunkRequest(), createModelsChunkRequest(),
createModelsInstanceChunkRequest() createModelsInstanceChunkRequest()
@@ -247,38 +271,6 @@ const Models: React.FC = () => {
}; };
}, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]); }, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]);
useEffect(() => {
const handleOnWindowMessage = (event: any) => {
const data = event.data;
console.log(
'event.origin=======',
event.origin !== window.location.origin ||
data.type !== 'modelInstance',
data,
event.origin,
window.location.origin
);
if (
event.origin !== window.location.origin ||
data.type !== 'modelInstance'
) {
return;
}
if (document.visibilityState === 'hidden') {
console.log('isPageHidden=======', document.visibilityState, data.data);
setModelInstances(data.data);
}
};
window.addEventListener('message', handleOnWindowMessage);
return () => {
window.removeEventListener('message', handleOnWindowMessage);
};
}, []);
return ( return (
<TableContext.Provider <TableContext.Provider
value={{ value={{
@@ -293,6 +285,7 @@ const Models: React.FC = () => {
handlePageChange={handlePageChange} handlePageChange={handlePageChange}
handleDeleteSuccess={fetchData} handleDeleteSuccess={fetchData}
onViewLogs={handleOnViewLogs} onViewLogs={handleOnViewLogs}
allInstances={allInstances}
onCancelViewLogs={handleOnCancelViewLogs} onCancelViewLogs={handleOnCancelViewLogs}
queryParams={queryParams} queryParams={queryParams}
loading={dataSource.loading} loading={dataSource.loading}