Browse Source

pref: refactor data (#864)

* refactor: decouple renameCollection API

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* refactor: decouple Alias api

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* refactor: refact createIndex api

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* refactor: decouple load/release collection api

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* refactor: decouple more api

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* refactor: dropCollection API

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

* finish refactor

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

---------

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
Signed-off-by: shanghaikid <jiangruiyi@gmail.com>
ryjiang 4 days ago
parent
commit
af1aaf9210

+ 6 - 79
client/src/context/Data.tsx

@@ -3,10 +3,9 @@ import { authContext } from '@/context';
 import { DEFAULT_TREE_WIDTH } from '@/consts';
 import { useUIPrefs } from '@/context/hooks/useUIPrefs';
 import { useWebSocket } from '@/context/hooks/useWebSocket';
-import { useDatabaseManagement } from '@/context/hooks/useDatabaseuseManagement';
+import { useDatabaseManagement } from '@/context/hooks/useDatabaseManagement';
 import { useCollectionsManagement } from '@/context/hooks/useCollectionsManagement';
 import type { DataContextType } from './Types';
-import type { CollectionFullObject, ResStatus } from '@server/types';
 
 export const dataContext = createContext<DataContextType>({
   loading: true,
@@ -16,49 +15,10 @@ export const dataContext = createContext<DataContextType>({
   database: '',
   setDatabase: () => {},
   databases: [],
-  setDatabaseList: () => {},
-  createDatabase: async () => ({}) as ResStatus,
-  dropDatabase: async () => ({}) as ResStatus,
-  fetchDatabases: async () => {
-    return [];
-  },
+  fetchDatabases: async () => {},
   fetchCollections: async () => {},
-  fetchCollection: async () => {
-    return {} as CollectionFullObject;
-  },
+  fetchCollection: async () => {},
   batchRefreshCollections: async () => {},
-  createCollection: async () => {
-    return {} as CollectionFullObject;
-  },
-  loadCollection: async () => ({}) as ResStatus,
-  releaseCollection: async () => ({}) as ResStatus,
-  renameCollection: async () => {
-    return {} as CollectionFullObject;
-  },
-  duplicateCollection: async () => {
-    return {} as CollectionFullObject;
-  },
-  dropCollection: async () => {
-    return {
-      error_code: -1,
-      reason: '',
-    };
-  },
-  createIndex: async () => {
-    return {} as CollectionFullObject;
-  },
-  dropIndex: async () => {
-    return {} as CollectionFullObject;
-  },
-  createAlias: async () => {
-    return {} as CollectionFullObject;
-  },
-  dropAlias: async () => {
-    return {} as CollectionFullObject;
-  },
-  setCollectionProperty: async () => {
-    return {} as CollectionFullObject;
-  },
   ui: {
     tree: {
       width: DEFAULT_TREE_WIDTH,
@@ -77,16 +37,8 @@ export const DataProvider = (props: { children: React.ReactNode }) => {
   const { ui, setUIPref } = useUIPrefs();
 
   // Database Hook
-  const {
-    databases,
-    loadingDatabases,
-    database,
-    setDatabase,
-    fetchDatabases,
-    createDatabase,
-    dropDatabase,
-    setDatabaseList,
-  } = useDatabaseManagement();
+  const { databases, loadingDatabases, database, setDatabase, fetchDatabases } =
+    useDatabaseManagement();
 
   //  useCollections hook
   const {
@@ -96,17 +48,6 @@ export const DataProvider = (props: { children: React.ReactNode }) => {
     fetchCollections,
     fetchCollection,
     batchRefreshCollections,
-    createCollection,
-    loadCollection,
-    releaseCollection,
-    renameCollection,
-    duplicateCollection,
-    dropCollection,
-    createIndex,
-    dropIndex,
-    createAlias,
-    dropAlias,
-    setCollectionProperty,
     updateCollections,
   } = useCollectionsManagement(database);
 
@@ -137,24 +78,10 @@ export const DataProvider = (props: { children: React.ReactNode }) => {
         database,
         databases,
         setDatabase,
-        setDatabaseList,
-        createDatabase,
-        dropDatabase,
+        fetchCollection,
         fetchDatabases,
         fetchCollections,
-        fetchCollection,
         batchRefreshCollections,
-        createCollection,
-        loadCollection,
-        releaseCollection,
-        renameCollection,
-        duplicateCollection,
-        dropCollection,
-        createIndex,
-        dropIndex,
-        createAlias,
-        dropAlias,
-        setCollectionProperty,
         ui,
         setUIPref,
       }}

+ 9 - 44
client/src/context/Types.ts

@@ -1,9 +1,5 @@
 import { Dispatch, ReactElement, SetStateAction } from 'react';
 import type { NavInfo } from '@/router/Types';
-import type {
-  IndexCreateParam,
-  IndexManageParam,
-} from '@/pages/databases/collections/schema/Types';
 import type {
   CollectionObject,
   CollectionFullObject,
@@ -106,49 +102,18 @@ export type DataContextType = {
   loading: boolean;
   loadingDatabases: boolean;
   collections: CollectionObject[];
-  setCollections: Dispatch<SetStateAction<CollectionObject[]>>;
-  database: string;
-  setDatabase: Dispatch<SetStateAction<string>>;
   databases: DatabaseObject[];
-  setDatabaseList: Dispatch<SetStateAction<DatabaseObject[]>>;
-  batchRefreshCollections: (collectionNames: string[], key?: string) => void;
-
-  // APIs
-  // databases
-  fetchDatabases: () => Promise<DatabaseObject[]>;
-  createDatabase: (params: { db_name: string }) => Promise<ResStatus>;
-  dropDatabase: (params: { db_name: string }) => Promise<ResStatus>;
+  database: string;
 
-  // collections
+  setCollections: Dispatch<SetStateAction<CollectionObject[]>>;
+  setDatabase: Dispatch<SetStateAction<string>>;
+  batchRefreshCollections: (
+    collectionNames: string[],
+    key?: string
+  ) => Promise<void>;
+  fetchDatabases: () => Promise<void>;
   fetchCollections: () => Promise<void>;
-  fetchCollection: (name: string) => Promise<CollectionFullObject>;
-  createCollection: (data: any) => Promise<CollectionFullObject>;
-  loadCollection: (name: string, param?: any) => Promise<ResStatus>;
-  releaseCollection: (name: string) => Promise<ResStatus>;
-  renameCollection: (
-    name: string,
-    newName: string
-  ) => Promise<CollectionFullObject>;
-  duplicateCollection: (
-    name: string,
-    newName: string
-  ) => Promise<CollectionFullObject>;
-  dropCollection: (name: string) => Promise<ResStatus>;
-  createIndex: (param: IndexCreateParam) => Promise<CollectionFullObject>;
-  dropIndex: (params: IndexManageParam) => Promise<CollectionFullObject>;
-  createAlias: (
-    collectionName: string,
-    alias: string
-  ) => Promise<CollectionFullObject>;
-  dropAlias: (
-    collectionName: string,
-    alias: string
-  ) => Promise<CollectionFullObject>;
-  setCollectionProperty: (
-    collectionName: string,
-    key: string,
-    value: any
-  ) => Promise<CollectionFullObject>;
+  fetchCollection: (name: string, drop?: boolean) => Promise<void>;
   // UI preferences
   ui: {
     tree: {

+ 48 - 125
client/src/context/hooks/useCollectionsManagement.ts

@@ -1,11 +1,7 @@
 import { useCallback, useRef, useState, useEffect } from 'react';
 import { CollectionService, MilvusService } from '@/http';
-import { WS_EVENTS, WS_EVENTS_TYPE, LOADING_STATE } from '@server/utils/Const';
+import { WS_EVENTS, WS_EVENTS_TYPE } from '@server/utils/Const';
 import { checkIndexing, checkLoading } from '@server/utils/Shared';
-import type {
-  IndexCreateParam,
-  IndexManageParam,
-} from '@/pages/databases/collections/schema/Types';
 import type { CollectionObject, CollectionFullObject } from '@server/types';
 
 export function useCollectionsManagement(database: string) {
@@ -43,8 +39,16 @@ export function useCollectionsManagement(database: string) {
   );
 
   const updateCollections = useCallback(
-    (props: { collections: CollectionFullObject[]; database?: string }) => {
-      const { collections: updated = [], database: remote } = props;
+    (props: {
+      collections: CollectionFullObject[];
+      database?: string;
+      deletedNames?: string[];
+    }) => {
+      const {
+        collections: updated = [],
+        database: remote,
+        deletedNames = [],
+      } = props;
       if (
         remote !== databaseRef.current &&
         databaseRef.current !== undefined &&
@@ -54,14 +58,41 @@ export function useCollectionsManagement(database: string) {
       }
       detectLoadingIndexing(updated);
       setCollections(prev => {
+        // merge collections
         const prevMap = new Map(prev.map(c => [c.id, c]));
         updated.forEach(c => {
           prevMap.set(c.id, c);
         });
-        return Array.from(prevMap.values());
+        let merged = Array.from(prevMap.values());
+        // delete collections
+        if (deletedNames.length > 0) {
+          merged = merged.filter(
+            c => !deletedNames.includes(c.collection_name)
+          );
+        }
+        const newCollections = updated.filter(
+          c => !prev.some(p => p.collection_name === c.collection_name)
+        );
+        // sort collections
+        if (newCollections.length > 0) {
+          return merged.sort((a, b) => {
+            if (
+              a.loadedPercentage === b.loadedPercentage &&
+              a.schema &&
+              b.schema
+            ) {
+              if (a.schema.hasVectorIndex === b.schema.hasVectorIndex) {
+                return b.createdTime - a.createdTime;
+              }
+              return a.schema.hasVectorIndex ? -1 : 1;
+            }
+            return (b.loadedPercentage || 0) - (a.loadedPercentage || 0);
+          });
+        }
+        return merged;
       });
     },
-    [detectLoadingIndexing] // Removed database dependency
+    [detectLoadingIndexing]
   );
 
   const refreshCollectionsDebounceMapRef = useRef<
@@ -91,14 +122,17 @@ export function useCollectionsManagement(database: string) {
     }
   };
 
-  const fetchCollection = async (name: string) => {
-    const res = await CollectionService.getCollection(name);
-    updateCollections({ collections: [res] });
-    return res;
+  const fetchCollection = async (name: string, drop?: boolean) => {
+    if (drop) {
+      updateCollections({ collections: [], deletedNames: [name] });
+    } else {
+      const res = await CollectionService.getCollection(name);
+      updateCollections({ collections: [res] });
+    }
   };
 
   const batchRefreshCollections = useCallback(
-    (collectionNames: string[], key: string = 'default') => {
+    async (collectionNames: string[], key: string = 'default') => {
       let ref = refreshCollectionsDebounceMapRef.current.get(key);
       if (!ref) {
         ref = { timer: null, names: [], pending: new Set() };
@@ -150,106 +184,6 @@ export function useCollectionsManagement(database: string) {
     [collections, updateCollections] // Removed database dependency
   );
 
-  const createCollection = async (data: any) => {
-    const newCollection = await CollectionService.createCollection(data);
-    const filteredCollections = collections.filter(
-      c => c.collection_name !== newCollection.collection_name
-    );
-    const newCollections = filteredCollections.concat(newCollection).sort((a, b) => {
-      if (a.loadedPercentage === b.loadedPercentage && a.schema && b.schema) {
-        if (a.schema.hasVectorIndex === b.schema.hasVectorIndex) {
-          return b.createdTime - a.createdTime;
-        }
-        return a.schema.hasVectorIndex ? -1 : 1;
-      }
-      return (b.loadedPercentage || 0) - (a.loadedPercentage || 0);
-    });
-    setCollections(newCollections);
-    return newCollection;
-  };
-
-  const loadCollection = async (name: string, param?: any) => {
-    const res = await CollectionService.loadCollection(name, param);
-    const collection = collections.find(
-      v => v.collection_name === name
-    ) as CollectionFullObject;
-    if (collection) {
-      collection.loadedPercentage = 0;
-      collection.loaded = false;
-      collection.status = LOADING_STATE.LOADING;
-    }
-    updateCollections({ collections: [collection] });
-    return res;
-  };
-
-  const releaseCollection = async (name: string) => {
-    return await CollectionService.releaseCollection(name);
-  };
-
-  const renameCollection = async (name: string, newName: string) => {
-    const newCollection = await CollectionService.renameCollection(name, {
-      new_collection_name: newName,
-    });
-    updateCollections({ collections: [newCollection] });
-    return newCollection;
-  };
-
-  const duplicateCollection = async (name: string, newName: string) => {
-    const newCollection = await CollectionService.duplicateCollection(name, {
-      new_collection_name: newName,
-    });
-    setCollections(prev => [...prev, newCollection]);
-    return newCollection;
-  };
-
-  const dropCollection = async (name: string) => {
-    const dropped = await CollectionService.dropCollection(name);
-    if (dropped.error_code === 'Success') {
-      setCollections(prev => prev.filter(v => v.collection_name !== name));
-    }
-    return dropped;
-  };
-
-  const createIndex = async (param: IndexCreateParam) => {
-    const newCollection = await CollectionService.createIndex(param);
-    updateCollections({ collections: [newCollection] });
-    return newCollection;
-  };
-
-  const dropIndex = async (params: IndexManageParam) => {
-    const { data } = await CollectionService.dropIndex(params);
-    updateCollections({ collections: [data] });
-    return data;
-  };
-
-  const createAlias = async (collectionName: string, alias: string) => {
-    const newCollection = await CollectionService.createAlias(collectionName, {
-      alias,
-    });
-    updateCollections({ collections: [newCollection] });
-    return newCollection;
-  };
-
-  const dropAlias = async (collectionName: string, alias: string) => {
-    const { data } = await CollectionService.dropAlias(collectionName, {
-      alias,
-    });
-    updateCollections({ collections: [data] });
-    return data;
-  };
-
-  const setCollectionProperty = async (
-    collectionName: string,
-    key: string,
-    value: any
-  ) => {
-    const newCollection = await CollectionService.setProperty(collectionName, {
-      [key]: value,
-    });
-    updateCollections({ collections: [newCollection] });
-    return newCollection;
-  };
-
   return {
     collections,
     setCollections,
@@ -257,17 +191,6 @@ export function useCollectionsManagement(database: string) {
     fetchCollections,
     fetchCollection,
     batchRefreshCollections,
-    createCollection,
-    loadCollection,
-    releaseCollection,
-    renameCollection,
-    duplicateCollection,
-    dropCollection,
-    createIndex,
-    dropIndex,
-    createAlias,
-    dropAlias,
-    setCollectionProperty,
     updateCollections,
   };
 }

+ 13 - 38
client/src/context/hooks/useDatabaseuseManagement.ts → client/src/context/hooks/useDatabaseManagement.ts

@@ -12,61 +12,39 @@ export const useDatabaseManagement = () => {
 
   // API: fetch databases
   const fetchDatabases = useCallback(
-    async (updateLoading?: boolean) => {
+    async (updateLoading?: boolean): Promise<void> => {
       try {
         updateLoading && setLoadingDatabases(true);
         const newDatabases = await DatabaseService.listDatabases();
-        // if no database, logout
         if (newDatabases.length === 0) {
           logout();
+          return;
         }
         setDatabases(newDatabases);
-        return newDatabases;
+
+        setDatabase(prev =>
+          newDatabases.some(db => db.name === prev)
+            ? prev
+            : newDatabases[0].name
+        );
+      } catch (error) {
+        console.error('Failed to fetch databases:', error);
       } finally {
         updateLoading && setLoadingDatabases(false);
       }
     },
     [logout]
-  ); // Added logout dependency
-
-  // API: create database
-  const createDatabase = useCallback(
-    async (params: { db_name: string }) => {
-      const res = await DatabaseService.createDatabase(params);
-      await fetchDatabases();
-      return res;
-    },
-    [fetchDatabases]
-  ); // Added fetchDatabases dependency
-
-  // API: delete database
-  const dropDatabase = useCallback(
-    async (params: { db_name: string }) => {
-      const res = await DatabaseService.dropDatabase(params);
-      const newDatabases = await fetchDatabases();
-      // Switch to the first available database after deletion
-      if (newDatabases.length > 0) {
-        setDatabase(newDatabases[0].name);
-      } else {
-        // Handle case where no databases are left (e.g., logout or show message)
-        logout();
-      }
-      return res;
-    },
-    [fetchDatabases, logout]
-  ); // Added fetchDatabases and logout dependencies
+  );
 
   // Effect to fetch initial databases when authenticated
   useEffect(() => {
     if (isAuth) {
-      // Update database from auth context when auth state changes
-      setDatabase(authReq.database);
-      // Fetch databases immediately when authenticated
+      if (database !== authReq.database) setDatabase(authReq.database);
       fetchDatabases(true);
     } else {
       // Clear data when not authenticated
       setDatabases([]);
-      setLoadingDatabases(true);
+      setLoadingDatabases(false);
     }
   }, [isAuth, authReq.database, fetchDatabases]); // Added fetchDatabases dependency
 
@@ -84,8 +62,5 @@ export const useDatabaseManagement = () => {
     database,
     setDatabase,
     fetchDatabases,
-    createDatabase,
-    dropDatabase,
-    setDatabaseList: setDatabases, // Keep setDatabaseList for compatibility if needed, though setDatabases is standard
   };
 };

+ 0 - 11
client/src/http/BaseModel.ts

@@ -63,17 +63,6 @@ export default class BaseModel {
     return response.data?.data as T;
   }
 
-  /**
-   * Batch delete resources
-   */
-  static async batchDelete<T>(options: RequestParams): Promise<T> {
-    return this.create<T>({
-      ...options,
-      method: 'post',
-      path: `${options.path}/batch-delete`,
-    });
-  }
-
   /**
    * Custom query
    */

+ 13 - 16
client/src/http/Collection.service.ts

@@ -50,7 +50,7 @@ export class CollectionService extends BaseModel {
   }
 
   static createCollection(data: any) {
-    return super.create<CollectionFullObject>({ path: `collections`, data });
+    return super.create<ResStatus>({ path: `collections`, data });
   }
 
   static dropCollection(collectionName: string) {
@@ -72,13 +72,10 @@ export class CollectionService extends BaseModel {
     });
   }
 
-  static renameCollection(
-    collectionName: string,
-    params: { new_collection_name: string }
-  ) {
-    return super.create<CollectionFullObject>({
+  static renameCollection(collectionName: string, new_collection_name: string) {
+    return super.create<ResStatus>({
       path: `/collections/${collectionName}`,
-      data: params,
+      data: { new_collection_name: new_collection_name },
     });
   }
 
@@ -91,11 +88,11 @@ export class CollectionService extends BaseModel {
 
   static duplicateCollection(
     collectionName: string,
-    params: { new_collection_name: string }
+    new_collection_name: string
   ) {
     return super.create<CollectionFullObject>({
       path: `/collections/${collectionName}/duplicate`,
-      data: params,
+      data: { new_collection_name: new_collection_name },
     });
   }
 
@@ -113,16 +110,16 @@ export class CollectionService extends BaseModel {
     });
   }
 
-  static createAlias(collectionName: string, params: { alias: string }) {
+  static createAlias(collectionName: string, alias: string) {
     return super.create<CollectionFullObject>({
       path: `/collections/${collectionName}/alias`,
-      data: params,
+      data: { alias: alias },
     });
   }
 
-  static dropAlias(collectionName: string, params: { alias: string }) {
-    return super.delete<{ data: CollectionFullObject }>({
-      path: `/collections/${collectionName}/alias/${params.alias}`,
+  static dropAlias(collectionName: string, alias: string) {
+    return super.delete<ResStatus>({
+      path: `/collections/${collectionName}/alias/${alias}`,
     });
   }
 
@@ -130,7 +127,7 @@ export class CollectionService extends BaseModel {
     const path = `/collections/index`;
     const type: ManageRequestMethods = ManageRequestMethods.CREATE;
 
-    return super.create<CollectionFullObject>({
+    return super.create<ResStatus>({
       path,
       data: { ...param, type },
     });
@@ -140,7 +137,7 @@ export class CollectionService extends BaseModel {
     const path = `/collections/index`;
     const type: ManageRequestMethods = ManageRequestMethods.DELETE;
 
-    return super.batchDelete<{ data: CollectionFullObject }>({
+    return super.query<ResStatus>({
       path,
       data: { ...param, type },
     });

+ 7 - 2
client/src/pages/databases/collections/Aliases.tsx

@@ -7,6 +7,7 @@ import CreateAliasDialog from '@/pages/dialogs/CreateAliasDialog';
 import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
 import { makeStyles } from '@mui/styles';
 import type { CollectionObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   wrapper: {
@@ -29,7 +30,7 @@ export interface AliasesProps {
 }
 
 export default function Aliases(props: AliasesProps) {
-  const { dropAlias } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
 
   const {
     aliases,
@@ -86,7 +87,11 @@ export default function Aliases(props: AliasesProps) {
     collection: CollectionObject;
     alias: string;
   }) => {
-    await dropAlias(params.collection.collection_name, params.alias);
+    await CollectionService.dropAlias(
+      params.collection.collection_name,
+      params.alias
+    );
+    await fetchCollection(params.collection.collection_name);
     openSnackBar(successTrans('delete', { name: collectionTrans('alias') }));
     handleCloseDialog();
     await onDelete(collection.collection_name);

+ 3 - 2
client/src/pages/databases/collections/Collections.tsx

@@ -135,7 +135,7 @@ const Collections = () => {
               <CreateCollectionDialog
                 onCreate={collection_name => {
                   //navigate to the new collection
-                 navigate(`/databases/${database}/${collection_name}/schema`);
+                  navigate(`/databases/${database}/${collection_name}/schema`);
                 }}
               />
             ),
@@ -253,7 +253,8 @@ const Collections = () => {
           params: {
             component: (
               <RenameCollectionDialog
-                cb={async () => {
+                cb={async (newName: string) => {
+                  await fetchCollection(newName);
                   setSelectedCollections([]);
                 }}
                 collection={selectedCollections[0]}

+ 6 - 3
client/src/pages/databases/collections/schema/IndexTypeElement.tsx

@@ -14,6 +14,7 @@ import CustomButton from '@/components/customButton/CustomButton';
 import { makeStyles } from '@mui/styles';
 import { isVectorType } from '@/utils';
 import type { FieldObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   wrapper: {
@@ -73,7 +74,7 @@ const IndexTypeElement: FC<{
   disabledTooltip?: string;
   cb?: (collectionName: string) => void;
 }> = ({ field, collectionName, cb, disabled }) => {
-  const { createIndex, dropIndex } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
 
   const classes = useStyles();
   // set empty string as default status
@@ -95,7 +96,8 @@ const IndexTypeElement: FC<{
       index_name,
       extra_params: params,
     };
-    await createIndex(indexCreateParam);
+    await CollectionService.createIndex(indexCreateParam);
+    await fetchCollection(collectionName);
     // reset status to default empty string
     handleCloseDialog();
     openSnackBar(indexTrans('createSuccess'));
@@ -128,7 +130,8 @@ const IndexTypeElement: FC<{
       index_name: field.index.index_name,
     };
 
-    await dropIndex(indexDeleteParam);
+    await CollectionService.dropIndex(indexDeleteParam);
+    await fetchCollection(collectionName);
     cb && (await cb(collectionName));
     handleCloseDialog();
     openSnackBar(successTrans('delete', { name: indexTrans('index') }));

+ 4 - 2
client/src/pages/dialogs/CreateAliasDialog.tsx

@@ -9,6 +9,7 @@ import { useFormValidation } from '@/hooks';
 import { makeStyles } from '@mui/styles';
 import type { ITextfieldConfig } from '@/components/customInput/Types';
 import type { CollectionObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   desc: {
@@ -22,7 +23,7 @@ export interface CreateAliasProps {
 }
 
 const CreateAliasDialog: FC<CreateAliasProps> = props => {
-  const { createAlias } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
   const { handleCloseDialog } = useContext(rootContext);
 
   const { cb, collection } = props;
@@ -49,7 +50,8 @@ const CreateAliasDialog: FC<CreateAliasProps> = props => {
   };
 
   const handleConfirm = async () => {
-    await createAlias(collection.collection_name, form.alias);
+    await CollectionService.createAlias(collection.collection_name, form.alias);
+    await fetchCollection(collection.collection_name);
     handleCloseDialog();
     cb && (await cb(collection));
   };

+ 6 - 2
client/src/pages/dialogs/CreateCollectionDialog.tsx

@@ -28,6 +28,7 @@ import type {
   CollectionCreateProps,
   CreateField,
 } from '../databases/collections/Types';
+import { CollectionService } from '@/http';
 
 // Add this type at the top of your file or in a relevant types file
 interface BM25Function {
@@ -40,7 +41,7 @@ interface BM25Function {
 }
 
 const CreateCollectionDialog: FC<CollectionCreateProps> = ({ onCreate }) => {
-  const { createCollection } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
   const { handleCloseDialog, openSnackBar } = useContext(rootContext);
   const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
@@ -244,10 +245,13 @@ const CreateCollectionDialog: FC<CollectionCreateProps> = ({ onCreate }) => {
     };
 
     // create collection
-    await createCollection({
+    await CollectionService.createCollection({
       ...param,
     });
 
+    // refresh collection
+    await fetchCollection(param.collection_name);
+
     // show success message
     openSnackBar(
       successTrans('create', {

+ 6 - 2
client/src/pages/dialogs/CreateDatabaseDialog.tsx

@@ -9,6 +9,7 @@ import { formatForm } from '@/utils';
 import { CreateDatabaseParams } from '@/http';
 import { dataContext, rootContext } from '@/context';
 import { makeStyles } from '@mui/styles';
+import { DatabaseService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   input: {
@@ -22,7 +23,7 @@ export interface CreateDatabaseProps {
 
 const CreateDatabaseDialog: FC<CreateDatabaseProps> = ({ onCreate }) => {
   // context
-  const { createDatabase } = useContext(dataContext);
+  const { fetchDatabases } = useContext(dataContext);
   const { openSnackBar, handleCloseDialog } = useContext(rootContext);
 
   // i18n
@@ -73,9 +74,12 @@ const CreateDatabaseDialog: FC<CreateDatabaseProps> = ({ onCreate }) => {
 
   const handleCreate = async () => {
     setLoading(true);
-    const res = await createDatabase(form).finally(() => {
+    // create database
+    await DatabaseService.createDatabase(form).finally(() => {
       setLoading(false);
     });
+    // refresh database list
+    await fetchDatabases();
 
     openSnackBar(successTrans('create', { name: dbTrans('database') }));
 

+ 4 - 2
client/src/pages/dialogs/DropCollectionDialog.tsx

@@ -3,11 +3,12 @@ import { useTranslation } from 'react-i18next';
 import { rootContext, dataContext } from '@/context';
 import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
 import { DropCollectionProps } from './Types';
+import { CollectionService } from '@/http';
 
 const DropCollectionDialog: FC<DropCollectionProps> = props => {
   const { collections, onDelete } = props;
   const { handleCloseDialog, openSnackBar } = useContext(rootContext);
-  const { dropCollection } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
   const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
   const { t: successTrans } = useTranslation('success');
@@ -16,7 +17,8 @@ const DropCollectionDialog: FC<DropCollectionProps> = props => {
   const handleDelete = async () => {
     const res = [];
     for (const item of collections) {
-      res.push(await dropCollection(item.collection_name));
+      res.push(await CollectionService.dropCollection(item.collection_name));
+      fetchCollection(item.collection_name, true);
     }
 
     // show success message

+ 8 - 2
client/src/pages/dialogs/DuplicateCollectionDialog.tsx

@@ -9,6 +9,7 @@ import { useFormValidation } from '@/hooks';
 import { ITextfieldConfig } from '@/components/customInput/Types';
 import { makeStyles } from '@mui/styles';
 import type { CollectionObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   wrapper: {
@@ -27,7 +28,7 @@ export interface DuplicateCollectionDialogProps {
 }
 
 const DuplicateCollectionDialog: FC<DuplicateCollectionDialogProps> = props => {
-  const { duplicateCollection } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
 
   const { cb, collection, collections } = props;
   const [form, setForm] = useState({
@@ -56,7 +57,12 @@ const DuplicateCollectionDialog: FC<DuplicateCollectionDialogProps> = props => {
 
   const handleConfirm = async () => {
     // duplicate
-    await duplicateCollection(collection.collection_name, form.duplicate);
+    await CollectionService.duplicateCollection(
+      collection.collection_name,
+      form.duplicate
+    );
+    //refresh collection
+    await fetchCollection(form.duplicate);
     // show success message
     openSnackBar(
       successTrans('duplicate', {

+ 6 - 7
client/src/pages/dialogs/EditMmapDialog.tsx

@@ -70,7 +70,7 @@ const EditMmapDialog: FC<EditMmapProps> = props => {
   const classes = useStyles();
 
   const { handleCloseDialog, openSnackBar } = useContext(rootContext);
-  const { setCollectionProperty } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
 
   const { t: dialogTrans } = useTranslation('dialog');
   const { t: btnTrans } = useTranslation('btn');
@@ -160,14 +160,12 @@ const EditMmapDialog: FC<EditMmapProps> = props => {
     // Make the API call to update mmap settings
     try {
       if (pendingCollectionMmap !== isCollectionMmapEnabled) {
-        await setCollectionProperty(
-          collection.collection_name,
-          'mmap.enabled',
-          pendingCollectionMmap
-        );
+        await CollectionService.setProperty(collection.collection_name, {
+          'mmap.enabled': pendingCollectionMmap,
+        });
       }
       if (pendingChanges.length > 0) {
-        const res = await CollectionService.updateMmap(
+        await CollectionService.updateMmap(
           collection.collection_name,
           pendingChanges
         );
@@ -181,6 +179,7 @@ const EditMmapDialog: FC<EditMmapProps> = props => {
       console.error('Error updating mmap settings:', error);
     } finally {
       cb && (await cb());
+      await fetchCollection(collection.collection_name);
       handleCloseDialog();
     }
   };

+ 5 - 4
client/src/pages/dialogs/EditPropertyDialog.tsx

@@ -11,6 +11,7 @@ import { Property } from '@/consts';
 import { makeStyles } from '@mui/styles';
 import { DatabaseService } from '@/http';
 import type { CollectionObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   desc: {
@@ -26,7 +27,7 @@ export interface EditPropertyProps {
 }
 
 const EditPropertyDialog: FC<EditPropertyProps> = props => {
-  const { setCollectionProperty } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
   const { handleCloseDialog } = useContext(rootContext);
 
   const { cb, target, property } = props;
@@ -69,11 +70,11 @@ const EditPropertyDialog: FC<EditPropertyProps> = props => {
 
     switch (props.type) {
       case 'collection':
-        await setCollectionProperty(
+        await CollectionService.setProperty(
           (target as CollectionObject).collection_name,
-          property.key,
-          value
+          { [property.key]: value }
         );
+        await fetchCollection((target as CollectionObject).collection_name);
         break;
       case 'database':
         await DatabaseService.setProperty({

+ 8 - 2
client/src/pages/dialogs/LoadCollectionDialog.tsx

@@ -13,6 +13,7 @@ import CustomToolTip from '@/components/customToolTip/CustomToolTip';
 import icons from '@/components/icons/Icons';
 import type { CollectionObject } from '@server/types';
 import { makeStyles } from '@mui/styles';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   desc: {
@@ -37,7 +38,7 @@ const LoadCollectionDialog = (props: {
   onLoad?: (collection: CollectionObject) => void;
   isModifyReplica?: boolean;
 }) => {
-  const { loadCollection } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
   const classes = useStyles();
   const { collection, onLoad, isModifyReplica } = props;
   const { t: dialogTrans } = useTranslation('dialog');
@@ -107,7 +108,12 @@ const LoadCollectionDialog = (props: {
     try {
       setBtnDisabled(true);
       // load collection request
-      await loadCollection(collection.collection_name, params);
+      await CollectionService.loadCollection(
+        collection.collection_name,
+        params
+      );
+      // refresh collection
+      await fetchCollection(collection.collection_name);
 
       // show success message
       openSnackBar(

+ 6 - 2
client/src/pages/dialogs/ReleaseCollectionDialog.tsx

@@ -5,6 +5,7 @@ import DialogTemplate from '@/components/customDialog/DialogTemplate';
 import { rootContext, dataContext } from '@/context';
 import { makeStyles } from '@mui/styles';
 import type { CollectionObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   desc: {
@@ -18,7 +19,7 @@ const ReleaseCollectionDialog = (props: {
   collection: CollectionObject;
   onRelease?: (collection: CollectionObject) => void;
 }) => {
-  const { releaseCollection } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
 
   const classes = useStyles();
 
@@ -36,7 +37,10 @@ const ReleaseCollectionDialog = (props: {
     setDisabled(true);
     try {
       // release collection
-      await releaseCollection(collection.collection_name);
+      await CollectionService.releaseCollection(collection.collection_name);
+
+      // refresh collection
+      await fetchCollection(collection.collection_name);
 
       // show success message
       openSnackBar(

+ 3 - 4
client/src/pages/dialogs/RenameCollectionDialog.tsx

@@ -1,7 +1,7 @@
 import { FC, useContext, useMemo, useState } from 'react';
 import { Typography, Theme } from '@mui/material';
 import { useTranslation } from 'react-i18next';
-import { rootContext, dataContext } from '@/context';
+import { rootContext } from '@/context';
 import { formatForm } from '@/utils';
 import { useFormValidation } from '@/hooks';
 import DialogTemplate from '@/components/customDialog/DialogTemplate';
@@ -9,6 +9,7 @@ import CustomInput from '@/components/customInput/CustomInput';
 import { makeStyles } from '@mui/styles';
 import type { ITextfieldConfig } from '@/components/customInput/Types';
 import type { CollectionObject } from '@server/types';
+import { CollectionService } from '@/http';
 
 const useStyles = makeStyles((theme: Theme) => ({
   desc: {
@@ -23,8 +24,6 @@ export interface RenameCollectionProps {
 }
 
 const RenameCollectionDialog: FC<RenameCollectionProps> = props => {
-  const { renameCollection } = useContext(dataContext);
-
   const { collection, cb } = props;
   const [form, setForm] = useState({
     new_collection_name: '',
@@ -51,7 +50,7 @@ const RenameCollectionDialog: FC<RenameCollectionProps> = props => {
   };
 
   const handleConfirm = async () => {
-    await renameCollection(
+    await CollectionService.renameCollection(
       collection.collection_name,
       form.new_collection_name
     );

+ 8 - 7
client/src/pages/dialogs/ResetPropertyDialog.tsx

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
 import { rootContext, dataContext } from '@/context';
 import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
 import { Property } from '@/consts';
-import { DatabaseService } from '@/http';
+import { DatabaseService, CollectionService } from '@/http';
 import type { CollectionObject } from '@server/types';
 
 export interface EditPropertyProps {
@@ -15,7 +15,7 @@ export interface EditPropertyProps {
 
 const ResetPropertyDialog: FC<EditPropertyProps> = props => {
   // context
-  const { setCollectionProperty } = useContext(dataContext);
+  const { fetchCollection } = useContext(dataContext);
   const { handleCloseDialog } = useContext(rootContext);
   // props
   const { cb, target, type, property } = props;
@@ -28,11 +28,12 @@ const ResetPropertyDialog: FC<EditPropertyProps> = props => {
         if (!collection || !collection.schema) {
           return;
         }
-        await setCollectionProperty(
-          collection.collection_name,
-          property.key,
-          ''
-        );
+        // Reset the property in the collection schema
+        await CollectionService.setProperty(collection.collection_name, {
+          [property.key]: '',
+        });
+        // Refresh the collection to get the latest schema
+        await fetchCollection((target as CollectionObject).collection_name);
         break;
 
       case 'database':

+ 6 - 5
client/src/pages/home/DatabaseCard.tsx

@@ -2,13 +2,13 @@ import { FC, useContext } from 'react';
 import { Typography, useTheme, Box } from '@mui/material';
 import { useNavigate } from 'react-router-dom';
 import { useTranslation } from 'react-i18next';
-import { MilvusService } from '@/http';
+import { MilvusService, DatabaseService } from '@/http';
 import icons from '@/components/icons/Icons';
 import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
 import { rootContext, authContext } from '@/context';
 import CreateDatabaseDialog from '../dialogs/CreateDatabaseDialog';
 import { CREATE_DB } from './Home';
-import type { DatabaseObject, ResStatus } from '@server/types';
+import type { DatabaseObject } from '@server/types';
 import IconButton from '@mui/material/IconButton';
 import Tooltip from '@mui/material/Tooltip';
 
@@ -16,7 +16,7 @@ export interface DatabaseCardProps {
   wrapperClass?: string;
   database: DatabaseObject;
   setDatabase: (database: string) => void;
-  dropDatabase: (params: { db_name: string }) => Promise<ResStatus>;
+  fetchDatabases: () => void;
   isActive?: boolean;
 }
 
@@ -24,7 +24,7 @@ const DatabaseCard: FC<DatabaseCardProps> = ({
   database = { name: '', collections: [], createdTime: 0 },
   wrapperClass = '',
   setDatabase,
-  dropDatabase,
+  fetchDatabases,
   isActive = false,
 }) => {
   // context
@@ -54,7 +54,8 @@ const DatabaseCard: FC<DatabaseCardProps> = ({
   };
 
   const handleDelete = async () => {
-    await dropDatabase({ db_name: database.name });
+    await DatabaseService.dropDatabase({ db_name: database.name });
+    await fetchDatabases();
     openSnackBar(successTrans('delete', { name: dbTrans('database') }));
     await MilvusService.useDatabase({ database: 'default' });
     handleCloseDialog();

+ 3 - 3
client/src/pages/home/Home.tsx

@@ -50,7 +50,7 @@ const Home = () => {
     collections,
     loadingDatabases,
     setDatabase,
-    dropDatabase,
+    fetchDatabases,
   } = useContext(dataContext);
   const { data } = useContext(systemContext);
   const classes = useStyles();
@@ -108,7 +108,7 @@ const Home = () => {
                   database={db}
                   isActive={db.name === database}
                   setDatabase={setDatabase}
-                  dropDatabase={dropDatabase}
+                  fetchDatabases={fetchDatabases}
                   key={db.name}
                 />
               );
@@ -116,7 +116,7 @@ const Home = () => {
             <DatabaseCard
               database={CREATE_DB}
               setDatabase={setDatabase}
-              dropDatabase={dropDatabase}
+              fetchDatabases={fetchDatabases}
               key={CREATE_DB.name}
             />
           </div>

+ 9 - 64
server/src/collections/collections.service.ts

@@ -28,7 +28,6 @@ import {
   HybridSearchReq,
   SearchSimpleReq,
   LoadState,
-  ErrorCode,
   AlterCollectionFieldPropertiesReq,
   AlterIndexReq,
 } from '@zilliz/milvus2-sdk-node';
@@ -70,14 +69,7 @@ export class CollectionsService {
 
   async createCollection(clientId: string, data: CreateCollectionReq) {
     const { milvusClient } = clientCache.get(clientId);
-    const res = await milvusClient.createCollection(data);
-    const newCollection = (await this.getAllCollections(
-      clientId,
-      [data.collection_name],
-      data.db_name
-    )) as CollectionFullObject[];
-
-    return newCollection[0];
+    return await milvusClient.createCollection(data);
   }
 
   async describeUnformattedCollection(
@@ -194,15 +186,7 @@ export class CollectionsService {
 
   async renameCollection(clientId: string, data: RenameCollectionReq) {
     const { milvusClient } = clientCache.get(clientId);
-    await milvusClient.renameCollection(data);
-
-    const newCollection = (await this.getAllCollections(
-      clientId,
-      [data.new_collection_name],
-      data.db_name
-    )) as CollectionFullObject[];
-
-    return newCollection[0];
+    return await milvusClient.renameCollection(data);
   }
 
   async alterCollectionProperties(clientId: string, data: AlterCollectionReq) {
@@ -226,22 +210,17 @@ export class CollectionsService {
 
   async dropCollection(clientId: string, data: DropCollectionReq) {
     const { milvusClient } = clientCache.get(clientId);
-    const res = await milvusClient.dropCollection(data);
-    return res;
+    return await milvusClient.dropCollection(data);
   }
 
   async loadCollection(clientId: string, data: LoadCollectionReq) {
     const { milvusClient } = clientCache.get(clientId);
-    await milvusClient.loadCollection(data);
-
-    return data.collection_name;
+    return await milvusClient.loadCollection(data);
   }
 
   async loadCollectionAsync(clientId: string, data: LoadCollectionReq) {
     const { milvusClient } = clientCache.get(clientId);
-    await milvusClient.loadCollectionAsync(data);
-
-    return data.collection_name;
+    return await milvusClient.loadCollectionAsync(data);
   }
 
   async releaseCollection(clientId: string, data: ReleaseLoadCollectionReq) {
@@ -350,15 +329,7 @@ export class CollectionsService {
 
   async createAlias(clientId: string, data: CreateAliasReq) {
     const { milvusClient } = clientCache.get(clientId);
-    const res = await milvusClient.createAlias(data);
-
-    const newCollection = (await this.getAllCollections(
-      clientId,
-      [data.collection_name],
-      data.db_name
-    )) as CollectionFullObject[];
-
-    return newCollection[0];
+    return await milvusClient.createAlias(data);
   }
 
   async alterAlias(clientId: string, data: AlterAliasReq) {
@@ -727,20 +698,7 @@ export class CollectionsService {
 
   async createIndex(clientId: string, data: CreateIndexReq) {
     const { milvusClient } = clientCache.get(clientId);
-    const createIndex = await milvusClient.createIndex(data);
-
-    if (createIndex.error_code === ErrorCode.SUCCESS) {
-      // fetch new collections
-      const newCollection = (await this.getAllCollections(
-        clientId,
-        [data.collection_name],
-        data.db_name
-      )) as CollectionFullObject[];
-
-      return newCollection[0];
-    } else {
-      throw new Error(createIndex.reason);
-    }
+    return await milvusClient.createIndex(data);
   }
 
   async describeIndex(clientId: string, data: DescribeIndexReq) {
@@ -784,20 +742,7 @@ export class CollectionsService {
   }
 
   async dropIndex(clientId: string, data: DropIndexReq) {
-    const { milvusClient, database } = clientCache.get(clientId);
-    const dropIndex = await milvusClient.dropIndex(data);
-
-    if (dropIndex.error_code === ErrorCode.SUCCESS) {
-      // fetch new collections
-      const newCollection = (await this.getAllCollections(
-        clientId,
-        [data.collection_name],
-        data.db_name
-      )) as CollectionFullObject[];
-
-      return newCollection[0];
-    } else {
-      throw new Error(dropIndex.reason);
-    }
+    const { milvusClient } = clientCache.get(clientId);
+    return await milvusClient.dropIndex(data);
   }
 }