Browse Source

Merge branch 'milvus-io:main' into main

zhuanghong.chen 3 years ago
parent
commit
4327b76aa0

+ 64 - 0
client/src/components/customProgress/CustomLinearProgress.tsx

@@ -0,0 +1,64 @@
+import {
+  makeStyles,
+  withStyles,
+  Theme,
+  LinearProgress,
+  Tooltip,
+  Typography,
+} from '@material-ui/core';
+import { FC } from 'react';
+import { CustomLinearProgressProps } from './Types';
+
+const getProgressStyles = makeStyles((theme: Theme) => ({
+  wrapper: {
+    display: 'flex',
+    alignItems: 'center',
+  },
+  percent: {
+    minWidth: '35px',
+    marginLeft: theme.spacing(1),
+    color: '#010e29',
+  },
+}));
+
+const BorderLinearProgress = withStyles((theme: Theme) => ({
+  root: {
+    height: 10,
+    borderRadius: 8,
+    border: '1px solid #e9e9ed',
+    minWidth: 85,
+  },
+  colorPrimary: {
+    backgroundColor: '#fff',
+  },
+  bar: {
+    borderRadius: 5,
+    backgroundColor: theme.palette.primary.main,
+  },
+}))(LinearProgress);
+
+const CustomLinearProgress: FC<CustomLinearProgressProps> = ({
+  value,
+  tooltip = '',
+  wrapperClass = '',
+}) => {
+  const classes = getProgressStyles();
+
+  return (
+    <div className={`${classes.wrapper} ${wrapperClass}`}>
+      {tooltip !== '' ? (
+        <Tooltip title={tooltip} aria-label={tooltip} arrow>
+          <BorderLinearProgress variant="determinate" value={value} />
+        </Tooltip>
+      ) : (
+        <BorderLinearProgress variant="determinate" value={value} />
+      )}
+      <Typography
+        variant="body1"
+        className={classes.percent}
+      >{`${value}%`}</Typography>
+    </div>
+  );
+};
+
+export default CustomLinearProgress;

+ 6 - 0
client/src/components/customProgress/Types.ts

@@ -0,0 +1,6 @@
+export interface CustomLinearProgressProps {
+  tooltip?: string;
+  // percentage, e.g. 50 means complete 50%
+  value: number;
+  wrapperClass?: string;
+}

+ 3 - 1
client/src/http/Collection.ts

@@ -129,8 +129,10 @@ export class CollectionHttp extends BaseModel implements CollectionView {
     }
   }
 
+  // Befor milvus-2.0-rc3  will return '0'.
+  // If milvus is stable, we can remote this condition/
   get _createdTime(): string {
-    return this.createdTime
+    return this.createdTime && this.createdTime !== '0'
       ? dayjs(Number(this.createdTime)).format('YYYY-MM-DD HH:mm:ss')
       : '';
   }

+ 18 - 2
client/src/http/Index.ts

@@ -24,9 +24,9 @@ export class IndexHttp extends BaseModel implements IndexView {
   static async getIndexStatus(
     collectionName: string,
     fieldName: string
-  ): Promise<IndexState> {
+  ): Promise<{ state: IndexState }> {
     const path = `${this.BASE_URL}/state`;
-    return super.findAll({
+    return super.search({
       path,
       params: { collection_name: collectionName, field_name: fieldName },
     });
@@ -59,6 +59,22 @@ export class IndexHttp extends BaseModel implements IndexView {
     return super.batchDelete({ path, data: { ...param, type } });
   }
 
+  static async getIndexBuildProgress(
+    collectionName: string,
+    fieldName: string
+  ) {
+    const path = `${this.BASE_URL}/progress`;
+    return super.search({
+      path,
+      params: {
+        collection_name: collectionName,
+        field_name: fieldName,
+        // user can't set index_name, use empty string as its value
+        index_name: '',
+      },
+    });
+  }
+
   get _indexType() {
     return this.params.find(p => p.key === 'index_type')?.value || '';
   }

+ 10 - 1
client/src/http/Partition.ts

@@ -1,3 +1,4 @@
+import dayjs from 'dayjs';
 import { StatusEnum } from '../components/status/Types';
 import {
   PartitionManageParam,
@@ -11,7 +12,7 @@ export class PartitionHttp extends BaseModel implements PartitionData {
   private id!: string;
   private name!: string;
   private rowCount!: string;
-  private status!: StatusEnum;
+  private createdTime!: string;
 
   constructor(props: {}) {
     super(props);
@@ -83,4 +84,12 @@ export class PartitionHttp extends BaseModel implements PartitionData {
     // @TODO replace mock data
     return StatusEnum.unloaded;
   }
+
+  // Befor milvus-2.0-rc3  will return '0'.
+  // If milvus is stable, we can remote this condition/
+  get _createdTime(): string {
+    return this.createdTime && this.createdTime !== '0'
+      ? dayjs(Number(this.createdTime)).format('YYYY-MM-DD HH:mm:ss')
+      : '';
+  }
 }

+ 2 - 1
client/src/i18n/cn/index.ts

@@ -6,8 +6,9 @@ const indexTrans = {
   index: 'Index',
   metric: 'Metric Type',
   desc: 'Description',
+  creating: 'Creating Index',
 
-  createSuccess: 'Creating index successfully',
+  createSuccess: 'Start creating index',
   deleteWarning:
     'You are trying to delete an index. This action cannot be undone.',
 };

+ 1 - 0
client/src/i18n/cn/partition.ts

@@ -6,6 +6,7 @@ const partitionTrans = {
 
   id: 'ID',
   name: 'Name',
+  createdTime: 'Created Time',
   status: 'Status',
   rowCount: 'Entity Count',
   tooltip: 'data in one entity',

+ 3 - 1
client/src/i18n/en/index.ts

@@ -6,8 +6,10 @@ const indexTrans = {
   index: 'Index',
   desc: 'Description',
 
+  creating: 'Creating Index',
+
   metric: 'Metric Type',
-  createSuccess: 'Creating index successfully',
+  createSuccess: 'Start creating index',
   deleteWarning:
     'You are trying to delete an index. This action cannot be undone.',
 };

+ 1 - 0
client/src/i18n/en/partition.ts

@@ -6,6 +6,7 @@ const partitionTrans = {
 
   id: 'ID',
   name: 'Name',
+  createdTime: 'Created Time',
   status: 'Status',
   rowCount: 'Entity Count',
   tooltip: 'data in one entity',

+ 0 - 6
client/src/pages/collections/Collections.tsx

@@ -323,12 +323,6 @@ const Collections = () => {
   ];
 
   const colDefinitions: ColDefinitionsType[] = [
-    {
-      id: '_id',
-      align: 'left',
-      disablePadding: true,
-      label: collectionTrans('id'),
-    },
     {
       id: 'nameElement',
       align: 'left',

+ 1 - 1
client/src/pages/overview/collectionCard/CollectionCard.tsx

@@ -121,7 +121,7 @@ const CollectionCard: FC<CollectionCardProps> = ({
         <VectorSearchIcon classes={{ root: classes.search }} />
         {btnTrans('vectorSearch')}
       </CustomButton>
-      <CustomIconButton onClick={onReleaseClick}>
+      <CustomIconButton onClick={onReleaseClick} tooltip={btnTrans('release')}>
         <ReleaseIcon classes={{ root: classes.release }} />
       </CustomIconButton>
     </div>

+ 5 - 5
client/src/pages/partitions/Partitions.tsx

@@ -301,16 +301,16 @@ const Partitions: FC<{
 
   const colDefinitions: ColDefinitionsType[] = [
     {
-      id: '_id',
+      id: '_nameElement',
       align: 'left',
-      disablePadding: true,
-      label: t('id'),
+      disablePadding: false,
+      label: t('name'),
     },
     {
-      id: '_nameElement',
+      id: '_createdTime',
       align: 'left',
       disablePadding: false,
-      label: t('name'),
+      label: t('createdTime'),
     },
     // {
     //   id: '_statusElement',

+ 46 - 6
client/src/pages/schema/IndexTypeElement.tsx

@@ -8,14 +8,13 @@ import {
   IndexManageParam,
   ParamPair,
 } from './Types';
-import StatusIcon from '../../components/status/StatusIcon';
-import { ChildrenStatusType } from '../../components/status/Types';
 import { useTranslation } from 'react-i18next';
 import { makeStyles, Theme } from '@material-ui/core';
 import icons from '../../components/icons/Icons';
 import { rootContext } from '../../context/Root';
 import CreateIndex from './Create';
 import DeleteTemplate from '../../components/customDialog/DeleteDialogTemplate';
+import CustomLinearProgress from '../../components/customProgress/CustomLinearProgress';
 
 const useStyles = makeStyles((theme: Theme) => ({
   item: {
@@ -62,20 +61,24 @@ const useStyles = makeStyles((theme: Theme) => ({
   },
 }));
 
+let timer: NodeJS.Timeout | null = null;
+
 const IndexTypeElement: FC<{
   data: FieldView;
   collectionName: string;
   cb: (collectionName: string) => void;
 }> = ({ data, collectionName, cb }) => {
   const classes = useStyles();
-
-  const [status, setStatus] = useState<string>('');
+  // set in progress as defalut status
+  const [status, setStatus] = useState<string>(IndexState.InProgress);
 
   const { t: indexTrans } = useTranslation('index');
   const { t: btnTrans } = useTranslation('btn');
   const { t: dialogTrans } = useTranslation('dialog');
   const { t: successTrans } = useTranslation('success');
 
+  const [createProgress, setCreateProgress] = useState<number>(0);
+
   const { setDialog, handleCloseDialog, openSnackBar } =
     useContext(rootContext);
 
@@ -84,7 +87,7 @@ const IndexTypeElement: FC<{
 
   const fetchStatus = useCallback(async () => {
     if (data._indexType !== '') {
-      const status = await IndexHttp.getIndexStatus(
+      const { state: status } = await IndexHttp.getIndexStatus(
         collectionName,
         data._fieldName
       );
@@ -96,6 +99,40 @@ const IndexTypeElement: FC<{
     fetchStatus();
   }, [fetchStatus]);
 
+  const fetchProgress = useCallback(() => {
+    if (timer) {
+      clearTimeout(timer);
+    }
+    if (data._indexType !== '' && status === IndexState.InProgress) {
+      timer = setTimeout(async () => {
+        const res = await IndexHttp.getIndexBuildProgress(
+          collectionName,
+          data._fieldName
+        );
+
+        const { indexed_rows, total_rows } = res;
+        const percent = Number(indexed_rows) / Number(total_rows);
+        const value = Math.floor(percent * 100);
+        setCreateProgress(value);
+
+        if (value !== 100) {
+          fetchProgress();
+        } else {
+          timer && clearTimeout(timer);
+          // reset build progress
+          setCreateProgress(0);
+          // change index create status
+          setStatus(IndexState.Finished);
+        }
+      }, 500);
+    }
+  }, [collectionName, data._fieldName, status, data._indexType]);
+
+  // get index build progress
+  useEffect(() => {
+    fetchProgress();
+  }, [fetchProgress]);
+
   const requestCreateIndex = async (params: ParamPair[]) => {
     const indexCreateParam: IndexCreateParam = {
       collection_name: collectionName,
@@ -179,7 +216,10 @@ const IndexTypeElement: FC<{
       }
       default: {
         return status === IndexState.InProgress ? (
-          <StatusIcon type={ChildrenStatusType.CREATING} />
+          <CustomLinearProgress
+            value={createProgress}
+            tooltip={indexTrans('creating')}
+          />
         ) : (
           <Chip
             label={data._indexType}

+ 1 - 1
server/package.json

@@ -32,7 +32,7 @@
     "@nestjs/websockets": "^8.0.4",
     "@types/passport-jwt": "^3.0.5",
     "@types/passport-local": "^1.0.33",
-    "@zilliz/milvus2-sdk-node": "^1.0.6",
+    "@zilliz/milvus2-sdk-node": "^1.0.7",
     "body-parser": "^1.19.0",
     "cache-manager": "^3.4.4",
     "class-transformer": "^0.4.0",

+ 2 - 1
server/src/partitions/partitions.service.ts

@@ -14,7 +14,7 @@ import { ROW_COUNT } from '../utils/Const';
 
 @Injectable()
 export class PartitionsService {
-  constructor(private milvusService: MilvusService) { }
+  constructor(private milvusService: MilvusService) {}
 
   get milvusClient() {
     return this.milvusService.milvusClientGetter;
@@ -33,6 +33,7 @@ export class PartitionsService {
           name,
           id: res.partitionIDs[index],
           rowCount: findKeyValue(statistics.stats, ROW_COUNT),
+          createdTime: res.created_utc_timestamps[index],
         });
       }
     }

+ 3 - 3
server/src/schema/dto.ts

@@ -100,9 +100,9 @@ export class GetIndexProgress {
     description: 'index name',
   })
   @IsString()
-  @IsNotEmpty({
-    message: 'index_name is empty',
-  })
+  // @IsNotEmpty({
+  //   message: 'index_name is empty',
+  // })
   readonly index_name: string;
 
   @ApiProperty({

+ 4 - 4
server/yarn.lock

@@ -1319,10 +1319,10 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
-"@zilliz/milvus2-sdk-node@^1.0.6":
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/@zilliz/milvus2-sdk-node/-/milvus2-sdk-node-1.0.6.tgz#e4293395f7cb24a437a9df92d2059c3b7e8f1889"
-  integrity sha512-n1nIafhd7FOPF5js6FoeJ9OuNX0ujIUMkINQPZyBCg8vVILQoOqyaTLcBCcVnqa+ejg1b2KXHlcTYrxWTJfTtw==
+"@zilliz/milvus2-sdk-node@^1.0.7":
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/@zilliz/milvus2-sdk-node/-/milvus2-sdk-node-1.0.7.tgz#b3d0bedbf9e35662e76e716ddb99dc3fc781fc00"
+  integrity sha512-4DFNqDkELG/s4JHqlT6/yZOtMxBWSca1G+RGfj3UC3pg7ncAUuw7HSpScLJ0uWhdUABWroQC6AD0DLnHNGhjFQ==
   dependencies:
     "@grpc/grpc-js" "^1.2.12"
     "@grpc/proto-loader" "^0.6.0"