fix: update instances with full data
This commit is contained in:
@@ -47,6 +47,7 @@ const TableRow: React.FC<
|
||||
const childrenDataRef = useRef<any[]>([]);
|
||||
childrenDataRef.current = childrenData;
|
||||
const axiosToken = useRef<any>(null);
|
||||
const [updateChild, setUpdateChild] = useState(true);
|
||||
|
||||
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
||||
dataList: childrenData,
|
||||
@@ -111,6 +112,9 @@ const TableRow: React.FC<
|
||||
};
|
||||
|
||||
const filterUpdateChildrenHandler = () => {
|
||||
if (!expanded) {
|
||||
return;
|
||||
}
|
||||
const dataList = _.filter(tableContext.allChildren, (data: any) => {
|
||||
return _.get(data, [childParentKey]) === _.get(record, [rowKey]);
|
||||
});
|
||||
@@ -161,6 +165,8 @@ const TableRow: React.FC<
|
||||
pollTimer.current = setInterval(() => {
|
||||
handlePolling();
|
||||
}, 1000);
|
||||
} else {
|
||||
handleLoadChildren();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,17 +192,13 @@ const TableRow: React.FC<
|
||||
}
|
||||
}, [expandedRowKeys]);
|
||||
|
||||
useEffect(() => {
|
||||
if (expanded) {
|
||||
handleLoadChildren();
|
||||
}
|
||||
}, [expanded]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = async () => {
|
||||
if (document.visibilityState === 'hidden') {
|
||||
cacheDataListRef.current = [];
|
||||
// setChildrenData([]);
|
||||
setUpdateChild(false);
|
||||
} else {
|
||||
setUpdateChild(true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -208,15 +210,15 @@ const TableRow: React.FC<
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!firstLoad && expanded) {
|
||||
cacheDataListRef.current = childrenData;
|
||||
if (updateChild) {
|
||||
// for update watch data
|
||||
filterUpdateChildrenHandler();
|
||||
}
|
||||
return () => {
|
||||
chunkRequestRef.current?.current?.cancel?.();
|
||||
cacheDataListRef.current = [];
|
||||
};
|
||||
}, [firstLoad, expanded, tableContext.allChildren]);
|
||||
}, [updateChild, tableContext.allChildren]);
|
||||
|
||||
const renderRowPrefix = () => {
|
||||
if (expandable && rowSelection) {
|
||||
@@ -296,7 +298,8 @@ const TableRow: React.FC<
|
||||
renderChildrenData()
|
||||
) : (
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
image={loading ? null : Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description={loading ? null : undefined}
|
||||
style={{
|
||||
marginBlock: 0,
|
||||
height: 54
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
let bufferedData = '';
|
||||
|
||||
const findValidJSONStrings = (inputStr: string) => {
|
||||
const validJSONStrings = [];
|
||||
let startIndex = 0;
|
||||
|
||||
while (startIndex < inputStr.length) {
|
||||
const openingBraceIndex = inputStr.indexOf('{', startIndex);
|
||||
if (openingBraceIndex === -1) break; // No more opening braces
|
||||
|
||||
let closingBraceIndex = openingBraceIndex;
|
||||
let braceCount = 0;
|
||||
|
||||
// find couple of braces
|
||||
while (closingBraceIndex < inputStr.length) {
|
||||
if (inputStr[closingBraceIndex] === '{') {
|
||||
braceCount++;
|
||||
} else if (inputStr[closingBraceIndex] === '}') {
|
||||
braceCount--;
|
||||
}
|
||||
if (braceCount === 0) {
|
||||
break;
|
||||
}
|
||||
closingBraceIndex++;
|
||||
}
|
||||
|
||||
if (braceCount !== 0) {
|
||||
// no matching closing brace
|
||||
break;
|
||||
}
|
||||
|
||||
const jsonString = inputStr.substring(
|
||||
openingBraceIndex,
|
||||
closingBraceIndex + 1
|
||||
);
|
||||
|
||||
try {
|
||||
const parsedData = JSON.parse(jsonString);
|
||||
validJSONStrings.push(parsedData);
|
||||
startIndex = closingBraceIndex + 1;
|
||||
} catch (error) {
|
||||
// mabye invalid JSON
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
parsedJSON: validJSONStrings,
|
||||
remainingData: inputStr.slice(startIndex) // it is the not parsed data
|
||||
};
|
||||
};
|
||||
|
||||
// Web Worker
|
||||
self.onmessage = function (event) {
|
||||
bufferedData += event.data;
|
||||
|
||||
const { parsedJSON, remainingData } = findValidJSONStrings(bufferedData);
|
||||
|
||||
if (parsedJSON.length > 0) {
|
||||
postMessage(parsedJSON);
|
||||
}
|
||||
|
||||
// save the remaining data for the next message
|
||||
bufferedData = remainingData;
|
||||
};
|
||||
@@ -36,69 +36,6 @@ export const sliceJsonStr = (text: string) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
export const parseJsonStr = (list: string[]) => {
|
||||
return _.map(list, (str: string) => {
|
||||
return JSON.parse(str);
|
||||
});
|
||||
};
|
||||
|
||||
const findMatchingClosingBracket = (inputStr: string, startIndex: number) => {
|
||||
let count = 0;
|
||||
for (let i = startIndex; i < inputStr.length; i += 1) {
|
||||
if (inputStr[i] === '{') {
|
||||
count += 1;
|
||||
} else if (inputStr[i] === '}') {
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
if (count === 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
const findValidJSONStrings = (inputStr: string) => {
|
||||
const validJSONStrings: any[] = [];
|
||||
let startIndex = 0;
|
||||
|
||||
while (startIndex < inputStr.length) {
|
||||
const openingBraceIndex = inputStr.indexOf('{', startIndex);
|
||||
if (openingBraceIndex === -1) {
|
||||
break; // No more opening braces
|
||||
}
|
||||
|
||||
const closingBraceIndex = findMatchingClosingBracket(
|
||||
inputStr,
|
||||
openingBraceIndex
|
||||
);
|
||||
if (closingBraceIndex === -1) {
|
||||
// If no matching closing brace, set startIndex to next character
|
||||
startIndex = openingBraceIndex + 1;
|
||||
} else {
|
||||
const jsonString = inputStr.substring(
|
||||
openingBraceIndex,
|
||||
closingBraceIndex + 1
|
||||
);
|
||||
try {
|
||||
const data = JSON.parse(jsonString);
|
||||
validJSONStrings.push(data);
|
||||
} catch (error) {
|
||||
// Ignore invalid JSON
|
||||
}
|
||||
|
||||
startIndex = closingBraceIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return validJSONStrings;
|
||||
};
|
||||
|
||||
const parseData = (data: string) => {
|
||||
const res = findValidJSONStrings(data);
|
||||
return res;
|
||||
};
|
||||
|
||||
export const createAxiosToken = () => {
|
||||
const { CancelToken } = axios;
|
||||
const source = CancelToken.source();
|
||||
@@ -123,7 +60,7 @@ const useSetChunkRequest = () => {
|
||||
const particalConfig = { params: {}, contentType: 'json' };
|
||||
const timer = useRef<any>(null);
|
||||
const loadedSize = useRef(0);
|
||||
const bufferedDataRef = useRef('');
|
||||
const workerRef = useRef<any>(null);
|
||||
|
||||
const reset = () => {
|
||||
loaded.current = 0;
|
||||
@@ -172,6 +109,23 @@ const useSetChunkRequest = () => {
|
||||
cancelWatchRequest(watchRequestList.length - 4 || 1);
|
||||
}
|
||||
|
||||
if (contentType === 'json') {
|
||||
workerRef.current?.terminate();
|
||||
|
||||
workerRef.current = new Worker(
|
||||
// @ts-ignore
|
||||
new URL('./json-parser-worker.ts', import.meta.url)
|
||||
);
|
||||
|
||||
workerRef.current.onmessage = function (event: any) {
|
||||
const validJSON = event.data;
|
||||
if (validJSON.length > 0) {
|
||||
const result = resetResultSchema(validJSON);
|
||||
handler(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const { request: requestData } = await request(url, {
|
||||
params: {
|
||||
@@ -188,38 +142,17 @@ const useSetChunkRequest = () => {
|
||||
loaded.current = e.loaded || 0;
|
||||
total.current = e.total || 0;
|
||||
|
||||
let currentRes = sliceData(response, e.loaded, loadedSize);
|
||||
let result: any[] = [];
|
||||
let cres = currentRes;
|
||||
|
||||
if (contentType === 'json') {
|
||||
// Append the new data to the buffered data
|
||||
bufferedDataRef.current += currentRes;
|
||||
|
||||
// Find valid JSON strings in the buffered data
|
||||
let validJSON = findValidJSONStrings(bufferedDataRef.current);
|
||||
if (validJSON.length > 0) {
|
||||
result = resetResultSchema(validJSON);
|
||||
|
||||
// Calculate the position of the last complete JSON fragment, keeping the unfinished part
|
||||
const lastValidJSON = validJSON[validJSON.length - 1];
|
||||
const lastJSONIndex = bufferedDataRef.current.lastIndexOf(
|
||||
JSON.stringify(lastValidJSON)
|
||||
);
|
||||
bufferedDataRef.current = bufferedDataRef.current.slice(
|
||||
lastJSONIndex + JSON.stringify(lastValidJSON).length
|
||||
);
|
||||
}
|
||||
handler(result);
|
||||
let currentRes = sliceData(response, e.loaded, loadedSize);
|
||||
workerRef.current.postMessage(currentRes);
|
||||
} else {
|
||||
handler(currentRes);
|
||||
handler(response);
|
||||
}
|
||||
|
||||
console.log('chunkrequest===', {
|
||||
result,
|
||||
result: response,
|
||||
url,
|
||||
params,
|
||||
raw: cres
|
||||
params
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,7 +9,12 @@ import {
|
||||
import _ from 'lodash';
|
||||
import qs from 'query-string';
|
||||
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 { ListItem } from './config/types';
|
||||
|
||||
@@ -81,39 +86,60 @@ const Models: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
axiosToken?.cancel?.();
|
||||
axiosToken = createAxiosToken();
|
||||
setDataSource((pre) => {
|
||||
pre.loading = true;
|
||||
return { ...pre };
|
||||
});
|
||||
const getAllModelInstances = useCallback(async () => {
|
||||
try {
|
||||
instancesToken.current?.cancel?.();
|
||||
instancesToken.current = createAxiosToken();
|
||||
const params = {
|
||||
..._.pickBy(queryParams, (val: any) => !!val)
|
||||
page: 1,
|
||||
perPage: 100
|
||||
};
|
||||
const res: any = await queryModelsList(params, {
|
||||
cancelToken: axiosToken.token
|
||||
});
|
||||
setDataSource({
|
||||
dataList: res.items || [],
|
||||
loading: false,
|
||||
loadend: true,
|
||||
total: res.pagination.total,
|
||||
deletedIds: []
|
||||
const res: any = await queryModelsInstances(params, {
|
||||
token: instancesToken.current.token
|
||||
});
|
||||
cacheInsDataListRef.current = res.items || [];
|
||||
setModelInstances(res.items || []);
|
||||
} catch (error) {
|
||||
if (!isPageHidden.current) {
|
||||
// ignore
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchData = useCallback(
|
||||
async (loadingVal?: boolean) => {
|
||||
axiosToken?.cancel?.();
|
||||
axiosToken = createAxiosToken();
|
||||
setDataSource((pre) => {
|
||||
pre.loading = loadingVal ?? true;
|
||||
return { ...pre };
|
||||
});
|
||||
try {
|
||||
const params = {
|
||||
..._.pickBy(queryParams, (val: any) => !!val)
|
||||
};
|
||||
const res: any = await queryModelsList(params, {
|
||||
cancelToken: axiosToken.token
|
||||
});
|
||||
setDataSource({
|
||||
dataList: [],
|
||||
dataList: res.items || [],
|
||||
loading: false,
|
||||
loadend: true,
|
||||
total: dataSource.total,
|
||||
total: res.pagination.total,
|
||||
deletedIds: []
|
||||
});
|
||||
} catch (error) {
|
||||
if (!isPageHidden.current) {
|
||||
setDataSource({
|
||||
dataList: [],
|
||||
loading: false,
|
||||
loadend: true,
|
||||
total: dataSource.total,
|
||||
deletedIds: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [queryParams]);
|
||||
},
|
||||
[queryParams]
|
||||
);
|
||||
|
||||
const handlePageChange = useCallback(
|
||||
(page: number, pageSize: number | undefined) => {
|
||||
@@ -135,6 +161,7 @@ const Models: React.FC = () => {
|
||||
const updateInstanceHandler = (list: any) => {
|
||||
// filter the data
|
||||
_.each(list, (data: any) => {
|
||||
console.log('updateInstanceHandler====', data);
|
||||
updateInstanceChunkedList(data);
|
||||
});
|
||||
};
|
||||
@@ -166,7 +193,7 @@ const Models: React.FC = () => {
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
}, []);
|
||||
}, [updateInstanceHandler]);
|
||||
|
||||
const handleOnViewLogs = useCallback(() => {
|
||||
isPageHidden.current = true;
|
||||
@@ -174,13 +201,15 @@ const Models: React.FC = () => {
|
||||
cacheDataListRef.current = [];
|
||||
cacheInsDataListRef.current = [];
|
||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||
instancesToken.current?.cancel?.();
|
||||
}, []);
|
||||
|
||||
const handleOnCancelViewLogs = useCallback(async () => {
|
||||
isPageHidden.current = false;
|
||||
await getAllModelInstances();
|
||||
await createModelsInstanceChunkRequest();
|
||||
await createModelsChunkRequest();
|
||||
fetchData();
|
||||
fetchData(false);
|
||||
}, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]);
|
||||
|
||||
const handleSearch = useCallback(async () => {
|
||||
@@ -232,19 +261,25 @@ const Models: React.FC = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('modelInstances====', modelInstances);
|
||||
}, [modelInstances]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = async () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
isPageHidden.current = false;
|
||||
await getAllModelInstances();
|
||||
await createModelsInstanceChunkRequest();
|
||||
await createModelsChunkRequest();
|
||||
fetchData();
|
||||
fetchData(false);
|
||||
} else {
|
||||
isPageHidden.current = true;
|
||||
chunkRequedtRef.current?.current?.cancel?.();
|
||||
cacheDataListRef.current = [];
|
||||
cacheInsDataListRef.current = [];
|
||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||
instancesToken.current?.cancel?.();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user