chore: display downloading progress in model instance log

This commit is contained in:
jialin
2025-08-08 15:51:09 +08:00
parent c8a7ac7dc6
commit bb67a8cbbb
3 changed files with 49 additions and 15 deletions
+32 -9
View File
@@ -16,6 +16,7 @@ interface MessageProps {
chunked?: boolean; chunked?: boolean;
progress?: number; progress?: number;
percent?: number; percent?: number;
isDownloading?: boolean;
} }
class AnsiParser { class AnsiParser {
private cursorRow: number = 0; private cursorRow: number = 0;
@@ -32,6 +33,7 @@ class AnsiParser {
private chunked: boolean = true; // true: send data in chunks, false: send all data at once private chunked: boolean = true; // true: send data in chunks, false: send all data at once
private reminder: string = ''; private reminder: string = '';
private lines: string[] = []; private lines: string[] = [];
isDownloading: boolean = false;
private pageSize: number = 500; private pageSize: number = 500;
private colorMap = { private colorMap = {
'30': 'black', '30': 'black',
@@ -79,6 +81,10 @@ class AnsiParser {
this.chunked = chunked ?? true; this.chunked = chunked ?? true;
} }
public setIsDownloading(isDownloading: boolean) {
this.isDownloading = isDownloading;
}
private setId() { private setId() {
this.uid += 1; this.uid += 1;
return this.uid; return this.uid;
@@ -168,14 +174,18 @@ class AnsiParser {
const remainingText = input.slice(lastIndex); const remainingText = input.slice(lastIndex);
this.handleText(remainingText); this.handleText(remainingText);
const result = this.screen.map((row, index) => ({ // const result = this.screen.map((row, index) => ({
content: removeBracketsFromLine(row.join('')), // content: removeBracketsFromLine(row.join('')),
uid: `${this.page}-${index}` // uid: `${this.page}-${index}`
})); // }));
const result = this.screen.map((row, index) =>
removeBracketsFromLine(row.join(''))
);
return { return {
data: result, data: result,
lines: this.rawDataRows lines: this.rawDataRows,
remainder: ''
}; };
} }
@@ -219,12 +229,23 @@ class AnsiParser {
this.isProcessing = true; this.isProcessing = true;
while (this.taskQueue.length > 0) { while (this.taskQueue.length > 0) {
const input = this.reminder + this.taskQueue.shift(); let input = '';
if (this.isDownloading) {
input = this.taskQueue.shift() || '';
} else {
input = this.reminder + this.taskQueue.shift();
}
if (input) { if (input) {
try { try {
const result = this.processInputByLine(input); const result = this.isDownloading
this.reminder = result.remainder; ? this.processInput(input)
: this.processInputByLine(input);
if (!this.isDownloading) {
this.reminder = result.remainder;
}
if (this.chunked) { if (this.chunked) {
self.postMessage({ result: result.data, lines: result.lines }); self.postMessage({ result: result.data, lines: result.lines });
} else if (!this.isComplete) { } else if (!this.isComplete) {
@@ -273,9 +294,11 @@ self.onmessage = function (event: MessageEvent<MessageProps>) {
page, page,
isComplete = false, isComplete = false,
chunked = true, chunked = true,
percent = 0 percent = 0,
isDownloading = false
} = event.data; } = event.data;
parser.setIsDownloading(isDownloading);
parser.setPage(page); parser.setPage(page);
parser.setIsCompelete(isComplete); parser.setIsCompelete(isComplete);
parser.setChunked(chunked); parser.setChunked(chunked);
@@ -4,7 +4,6 @@ import classNames from 'classnames';
import _ from 'lodash'; import _ from 'lodash';
import React, { import React, {
forwardRef, forwardRef,
memo,
useCallback, useCallback,
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
@@ -25,10 +24,17 @@ interface LogsViewerProps {
tail?: number; tail?: number;
enableScorllLoad?: boolean; enableScorllLoad?: boolean;
diffHeight?: number; diffHeight?: number;
isDownloading?: boolean;
} }
const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => { const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
const { diffHeight, url, tail: defaultTail, enableScorllLoad = true } = props; const {
diffHeight,
url,
tail: defaultTail,
enableScorllLoad = true,
isDownloading
} = props;
const { pageSize, page, setPage, setTotalPage, totalPage } = const { pageSize, page, setPage, setTotalPage, totalPage } =
useLogsPagination(); useLogsPagination();
const { setChunkFetch } = useSetChunkFetch(); const { setChunkFetch } = useSetChunkFetch();
@@ -64,9 +70,10 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
}; };
const setCurrentData = (lines: string[]) => { const setCurrentData = (lines: string[]) => {
console.log('setCurrentData', lines);
const dataList = lines.map((line, index) => { const dataList = lines.map((line, index) => {
return { return {
content: removeBracketsFromLine(line), content: line,
uid: `${pageRef.current}-${index}` uid: `${pageRef.current}-${index}`
}; };
}); });
@@ -150,7 +157,8 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
logParseWorker.current.postMessage({ logParseWorker.current.postMessage({
inputStr: data, inputStr: data,
page: pageRef.current, page: pageRef.current,
reset: clearScreen.current reset: clearScreen.current,
isDownloading: isDownloading
}); });
clearScreen.current = false; clearScreen.current = false;
}; };
@@ -349,4 +357,4 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
); );
}); });
export default memo(LogsViewer); export default React.memo(LogsViewer);
@@ -4,7 +4,7 @@ import { useIntl } from '@umijs/max';
import { Modal } from 'antd'; import { Modal } from 'antd';
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { MODELS_API } from '../apis'; import { MODELS_API } from '../apis';
import { InstanceRealtimeLogStatus } from '../config'; import { InstanceRealtimeLogStatus, InstanceStatusMap } from '../config';
type ViewModalProps = { type ViewModalProps = {
open: boolean; open: boolean;
@@ -20,6 +20,7 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
const { setChunkRequest } = useSetChunkRequest(); const { setChunkRequest } = useSetChunkRequest();
const { open, url, onCancel, tail } = props || {}; const { open, url, onCancel, tail } = props || {};
const [enableScorllLoad, setEnableScorllLoad] = useState(true); const [enableScorllLoad, setEnableScorllLoad] = useState(true);
const [instanceState, setInstanceState] = useState<string>('');
const logsViewerRef = React.useRef<any>(null); const logsViewerRef = React.useRef<any>(null);
const requestRef = React.useRef<any>(null); const requestRef = React.useRef<any>(null);
const contentRef = React.useRef<any>(null); const contentRef = React.useRef<any>(null);
@@ -33,6 +34,7 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
const data = list?.find((item: any) => item.data?.id === props.id); const data = list?.find((item: any) => item.data?.id === props.id);
// state in InstanceRealtimeLogStatus will not enable scorll load, because it is in the trasisition state // state in InstanceRealtimeLogStatus will not enable scorll load, because it is in the trasisition state
if (data) { if (data) {
setInstanceState(data?.data?.state);
setEnableScorllLoad( setEnableScorllLoad(
() => !InstanceRealtimeLogStatus.includes(data?.data?.state) () => !InstanceRealtimeLogStatus.includes(data?.data?.state)
); );
@@ -111,6 +113,7 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
url={url} url={url}
tail={tail} tail={tail}
enableScorllLoad={enableScorllLoad} enableScorllLoad={enableScorllLoad}
isDownloading={instanceState !== InstanceStatusMap.Downloading}
params={{ params={{
follow: true follow: true
}} }}