Browse Source

support multiple sessions (#359)

* support multiple sessions

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

* update commit

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

* update title

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

* fix i18n

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

---------

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 1 year ago
parent
commit
c645a4a0d3

+ 3 - 10
client/src/components/layout/GlobalEffect.tsx

@@ -1,7 +1,6 @@
 import React, { useContext } from 'react';
 import axiosInstance from '@/http/Axios';
 import { rootContext, authContext } from '@/context';
-import { MILVUS_ADDRESS, LOGIN_USERNAME } from '@/consts';
 import { HTTP_STATUS_CODE } from '@server/utils/Const';
 
 let axiosResInterceptor: number | null = null;
@@ -9,7 +8,7 @@ let axiosResInterceptor: number | null = null;
 // we only take side effect here, nothing else
 const GlobalEffect = (props: { children: React.ReactNode }) => {
   const { openSnackBar } = useContext(rootContext);
-  const { setIsAuth, setAddress, setUsername } = useContext(authContext);
+  const { logout } = useContext(authContext);
 
   // catch axios error here
   if (axiosResInterceptor === null) {
@@ -24,17 +23,11 @@ const GlobalEffect = (props: { children: React.ReactNode }) => {
       },
       function (error: any) {
         const { response = {} } = error;
-        const reset = () => {
-          setIsAuth(false);
-          setAddress('');
-          setUsername('');
-          window.localStorage.removeItem(MILVUS_ADDRESS);
-          window.localStorage.removeItem(LOGIN_USERNAME);
-        };
+
         switch (response.status) {
           case HTTP_STATUS_CODE.UNAUTHORIZED:
           case HTTP_STATUS_CODE.FORBIDDEN:
-            setTimeout(reset, 2000);
+            setTimeout(logout, 1000);
             break;
           default:
             break;

+ 2 - 11
client/src/components/layout/Header.tsx

@@ -11,7 +11,6 @@ import AccountCircleIcon from '@material-ui/icons/AccountCircle';
 import { useNavigate } from 'react-router-dom';
 import { navContext, dataContext, authContext } from '@/context';
 import { MilvusService } from '@/http';
-import { MILVUS_ADDRESS, LOGIN_USERNAME } from '@/consts';
 import CustomSelector from '@/components/customSelector/CustomSelector';
 import icons from '../icons/Icons';
 import { HeaderType } from './Types';
@@ -72,8 +71,7 @@ const Header: FC<HeaderType> = props => {
   const classes = useStyles();
   const { navInfo } = useContext(navContext);
   const { database, databases, setDatabase } = useContext(dataContext);
-  const { address, setAddress, username, setUsername, setIsAuth } =
-    useContext(authContext);
+  const { address, username, logout } = useContext(authContext);
   const navigate = useNavigate();
 
   const { t: commonTrans } = useTranslation();
@@ -87,14 +85,7 @@ const Header: FC<HeaderType> = props => {
   };
 
   const handleLogout = async () => {
-    setAddress('');
-    setUsername('');
-    setIsAuth(false);
-    await MilvusService.closeConnection();
-    window.localStorage.removeItem(MILVUS_ADDRESS);
-    window.localStorage.removeItem(LOGIN_USERNAME);
-    // make sure we clear state in all pages
-    // navigate(0);
+    logout();
   };
 
   const useDatabase = async (database: string) => {

+ 1 - 1
client/src/consts/Localstorage.ts

@@ -1,5 +1,5 @@
 export const SESSION = 'CLOUD_SESSION';
-export const MILVUS_ADDRESS = 'milvus-address';
+export const MILVUS_CLIENT_ID = 'milvus-client-id';
 export const LOGIN_USERNAME = 'login-username';
 export const LAST_TIME_ADDRESS = 'last-time-address';
 export const LAST_TIME_DATABASE = 'last-time-database';

+ 13 - 24
client/src/context/Auth.tsx

@@ -1,6 +1,5 @@
 import { createContext, useEffect, useState } from 'react';
-import { MILVUS_ADDRESS, LOGIN_USERNAME } from '@/consts';
-import { MilvusService } from '@/http';
+import { MILVUS_CLIENT_ID, LAST_TIME_ADDRESS, LOGIN_USERNAME } from '@/consts';
 import { AuthContextType } from './Types';
 
 export const authContext = createContext<AuthContextType>({
@@ -8,6 +7,7 @@ export const authContext = createContext<AuthContextType>({
   address: '',
   username: '',
   isManaged: false,
+  logout: () => {},
   setAddress: () => {},
   setUsername: () => {},
   setIsAuth: () => {},
@@ -17,7 +17,7 @@ const { Provider } = authContext;
 export const AuthProvider = (props: { children: React.ReactNode }) => {
   // get milvus address from local storage
   const [address, setAddress] = useState<string>(
-    window.localStorage.getItem(MILVUS_ADDRESS) || ''
+    window.localStorage.getItem(LAST_TIME_ADDRESS) || ''
   );
   // get login username from local storage
   const [username, setUsername] = useState<string>(
@@ -26,28 +26,16 @@ export const AuthProvider = (props: { children: React.ReactNode }) => {
   const [isAuth, setIsAuth] = useState<boolean>(address !== '');
   // const isAuth = useMemo(() => !!address, [address]);
 
-  useEffect(() => {
-    // check if the milvus is still available
-    const check = async () => {
-      const milvusAddress = window.localStorage.getItem(MILVUS_ADDRESS) || '';
-      if (!milvusAddress) {
-        return;
-      }
-      const res = await MilvusService.check(milvusAddress);
-      setAddress(res.connected ? milvusAddress : '');
-      res.connected && setIsAuth(true);
-      if (!res.connected) {
-        window.localStorage.removeItem(MILVUS_ADDRESS);
-      }
+  const logout = () => {
+    // remove user data from local storage
+    window.localStorage.removeItem(MILVUS_CLIENT_ID);
+    window.localStorage.removeItem(LOGIN_USERNAME);
 
-      const username = window.localStorage.getItem(LOGIN_USERNAME) || '';
-      if (!username) {
-        return;
-      }
-      setUsername(username);
-    };
-    check();
-  }, [setAddress, setUsername]);
+    // update state
+    setAddress('');
+    setUsername('');
+    setIsAuth(false);
+  };
 
   useEffect(() => {
     document.title = address ? `${address} - Attu` : 'Attu';
@@ -62,6 +50,7 @@ export const AuthProvider = (props: { children: React.ReactNode }) => {
         setAddress,
         setUsername,
         setIsAuth,
+        logout,
         isManaged: address.includes('vectordb.zillizcloud.com'),
       }}
     >

+ 1 - 0
client/src/context/Types.ts

@@ -59,6 +59,7 @@ export type AuthContextType = {
   address: string;
   username: string;
   isManaged: boolean;
+  logout: Function;
   setAddress: Dispatch<SetStateAction<string>>;
   setUsername: Dispatch<SetStateAction<string>>;
   setIsAuth: Dispatch<SetStateAction<boolean>>;

+ 3 - 3
client/src/http/Axios.ts

@@ -1,5 +1,5 @@
 import axios from 'axios';
-import { MILVUS_ADDRESS } from '@/consts';
+import { MILVUS_CLIENT_ID } from '@/consts';
 
 // base hots url
 const DEFAULT_HOST_URL = `http://127.0.0.1:3000`;
@@ -23,9 +23,9 @@ const axiosInstance = axios.create({
 axiosInstance.interceptors.request.use(
   function (config) {
     // Do something before request is sent
-    const address = window.localStorage.getItem(MILVUS_ADDRESS);
+    const address = window.localStorage.getItem(MILVUS_CLIENT_ID);
 
-    address && (config.headers[MILVUS_ADDRESS] = address);
+    address && (config.headers[MILVUS_CLIENT_ID] = address);
 
     return config;
   },

+ 1 - 0
client/src/http/Milvus.service.ts

@@ -24,6 +24,7 @@ export class MilvusService extends BaseModel {
     return super.create({ path: this.CONNECT_URL, data }) as Promise<{
       address: string;
       database: string;
+      clientId: string;
     }>;
   }
 

+ 6 - 5
client/src/i18n/cn/success.ts

@@ -1,11 +1,12 @@
 const successTrans = {
   connect: '成功连接到milvus',
-  create: `{{name}}已被创建。`,
+  create: `{{name}}创建成功。`,
   load: `{{name}}正在加载。`,
-  delete: `{{name}}已成功删除。`,
-  release: `{{name}}已被释放。`,
-  update: `{{name}}已被更新。`,
-  rename: `{{name}}已被重命名。`,
+  delete: `{{name}}删除成功。`,
+  release: `{{name}}释放成功。`,
+  update: `{{name}}更新成功。`,
+  rename: `{{name}}重命名成功。`,
+  duplicate: `{{name}}复制成功.`,
 };
 
 export default successTrans;

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

@@ -6,6 +6,7 @@ const successTrans = {
   release: `{{name}} has been released.`,
   update: `{{name}} has been updated.`,
   rename: `{{name}} has been renamed.`,
+  duplicate: `{{name}} has been duplicated.`,
 };
 
 export default successTrans;

+ 7 - 2
client/src/pages/collections/Collections.tsx

@@ -394,6 +394,11 @@ const Collections = () => {
             component: (
               <DuplicateCollectionDialog
                 cb={async () => {
+                  openSnackBar(
+                    successTrans('duplicate', {
+                      name: collectionTrans('collection'),
+                    })
+                  );
                   setSelectedCollections([]);
                   await fetchData();
                 }}
@@ -404,9 +409,9 @@ const Collections = () => {
           },
         });
       },
-      label: collectionTrans('rename'),
+      label: collectionTrans('duplicate'),
       // tooltip: collectionTrans('deleteTooltip'),
-      disabledTooltip: collectionTrans('renameTooltip'),
+      disabledTooltip: collectionTrans('duplicateTooltip'),
       disabled: data => data.length !== 1,
     },
     {

+ 2 - 2
client/src/pages/connect/AuthForm.tsx

@@ -16,7 +16,7 @@ import {
   dataContext,
 } from '@/context';
 import {
-  MILVUS_ADDRESS,
+  MILVUS_CLIENT_ID,
   LOGIN_USERNAME,
   LAST_TIME_ADDRESS,
   MILVUS_URL,
@@ -211,7 +211,7 @@ export const AuthForm = (props: any) => {
     setDatabase(result.database);
 
     openSnackBar(successTrans('connect'));
-    window.localStorage.setItem(MILVUS_ADDRESS, form.address);
+    window.localStorage.setItem(MILVUS_CLIENT_ID, result.clientId);
     window.localStorage.setItem(LOGIN_USERNAME, form.username);
     // store address for next time using
     window.localStorage.setItem(LAST_TIME_ADDRESS, form.address);

+ 1 - 2
server/src/collections/collections.controller.ts

@@ -1,6 +1,5 @@
 import { NextFunction, Request, Response, Router } from 'express';
 import { dtoValidationMiddleware } from '../middleware/validation';
-import { milvusService } from '../milvus';
 import { CollectionsService } from './collections.service';
 import {
   CreateAliasDto,
@@ -19,7 +18,7 @@ export class CollectionController {
   private router: Router;
 
   constructor() {
-    this.collectionsService = new CollectionsService(milvusService);
+    this.collectionsService = new CollectionsService();
 
     this.router = Router();
   }

+ 30 - 24
server/src/collections/collections.service.ts

@@ -38,54 +38,56 @@ import { SchemaService } from '../schema/schema.service';
 export class CollectionsService {
   private schemaService: SchemaService;
 
-  constructor(private milvusService: MilvusService) {
-    this.schemaService = new SchemaService(milvusService);
+  constructor() {
+    this.schemaService = new SchemaService();
   }
 
   async getCollections(data?: ShowCollectionsReq) {
-    const res = await this.milvusService.client.showCollections(data);
+    const res = await MilvusService.activeMilvusClient.showCollections(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async createCollection(data: CreateCollectionReq) {
-    const res = await this.milvusService.client.createCollection(data);
+    const res = await MilvusService.activeMilvusClient.createCollection(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async describeCollection(data: DescribeCollectionReq) {
-    const res = await this.milvusService.client.describeCollection(data);
+    const res = await MilvusService.activeMilvusClient.describeCollection(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async renameCollection(data: RenameCollectionReq) {
-    const res = await this.milvusService.client.renameCollection(data);
+    const res = await MilvusService.activeMilvusClient.renameCollection(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async dropCollection(data: DropCollectionReq) {
-    const res = await this.milvusService.client.dropCollection(data);
+    const res = await MilvusService.activeMilvusClient.dropCollection(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async loadCollection(data: LoadCollectionReq) {
-    const res = await this.milvusService.client.loadCollection(data);
+    const res = await MilvusService.activeMilvusClient.loadCollection(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async releaseCollection(data: ReleaseLoadCollectionReq) {
-    const res = await this.milvusService.client.releaseCollection(data);
+    const res = await MilvusService.activeMilvusClient.releaseCollection(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async getCollectionStatistics(data: GetCollectionStatisticsReq) {
-    const res = await this.milvusService.client.getCollectionStatistics(data);
+    const res = await MilvusService.activeMilvusClient.getCollectionStatistics(
+      data
+    );
     throwErrorFromSDK(res.status);
     return res;
   }
@@ -93,7 +95,7 @@ export class CollectionsService {
   async count(data: CountReq) {
     let count = 0;
     try {
-      const countRes = await this.milvusService.client.count(data);
+      const countRes = await MilvusService.activeMilvusClient.count(data);
       count = countRes.data;
     } catch (error) {
       const collectionStatisticsRes = await this.getCollectionStatistics(data);
@@ -103,20 +105,20 @@ export class CollectionsService {
   }
 
   async insert(data: InsertReq) {
-    const res = await this.milvusService.client.insert(data);
+    const res = await MilvusService.activeMilvusClient.insert(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async deleteEntities(data: DeleteEntitiesReq) {
-    const res = await this.milvusService.client.deleteEntities(data);
+    const res = await MilvusService.activeMilvusClient.deleteEntities(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async vectorSearch(data: SearchReq) {
     const now = Date.now();
-    const res = await this.milvusService.client.search(data);
+    const res = await MilvusService.activeMilvusClient.search(data);
     const after = Date.now();
 
     throwErrorFromSDK(res.status);
@@ -125,25 +127,25 @@ export class CollectionsService {
   }
 
   async createAlias(data: CreateAliasReq) {
-    const res = await this.milvusService.client.createAlias(data);
+    const res = await MilvusService.activeMilvusClient.createAlias(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async alterAlias(data: AlterAliasReq) {
-    const res = await this.milvusService.client.alterAlias(data);
+    const res = await MilvusService.activeMilvusClient.alterAlias(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async dropAlias(data: DropAliasReq) {
-    const res = await this.milvusService.client.dropAlias(data);
+    const res = await MilvusService.activeMilvusClient.dropAlias(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async getReplicas(data: GetReplicasDto) {
-    const res = await this.milvusService.client.getReplicas(data);
+    const res = await MilvusService.activeMilvusClient.getReplicas(data);
     return res;
   }
 
@@ -153,7 +155,7 @@ export class CollectionsService {
     } & QueryDto
   ) {
     const now = Date.now();
-    const res = await this.milvusService.client.query(data);
+    const res = await MilvusService.activeMilvusClient.query(data);
 
     const after = Date.now();
 
@@ -337,31 +339,35 @@ export class CollectionsService {
   }
 
   async getCompactionState(data: GetCompactionStateReq) {
-    const res = await this.milvusService.client.getCompactionState(data);
+    const res = await MilvusService.activeMilvusClient.getCompactionState(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async getQuerySegmentInfo(data: GetQuerySegmentInfoReq) {
-    const res = await this.milvusService.client.getQuerySegmentInfo(data);
+    const res = await MilvusService.activeMilvusClient.getQuerySegmentInfo(
+      data
+    );
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async getPersistentSegmentInfo(data: GePersistentSegmentInfoReq) {
-    const res = await this.milvusService.client.getPersistentSegmentInfo(data);
+    const res = await MilvusService.activeMilvusClient.getPersistentSegmentInfo(
+      data
+    );
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async compact(data: CompactReq) {
-    const res = await this.milvusService.client.compact(data);
+    const res = await MilvusService.activeMilvusClient.compact(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async hasCollection(data: HasCollectionReq) {
-    const res = await this.milvusService.client.hasCollection(data);
+    const res = await MilvusService.activeMilvusClient.hasCollection(data);
     throwErrorFromSDK(res.status);
     return res;
   }

+ 2 - 2
server/src/crons/crons.controller.ts

@@ -3,7 +3,7 @@ import { dtoValidationMiddleware } from '../middleware/validation';
 import { CronsService, SchedulerRegistry } from './crons.service';
 import { collectionsService } from '../collections';
 import { ToggleCronJobByNameDto } from './dto';
-import { MILVUS_ADDRESS } from '../utils';
+import { MILVUS_CLIENT_ID } from '../utils';
 
 export class CronsController {
   private router: Router;
@@ -31,7 +31,7 @@ export class CronsController {
 
   async toggleCronJobByName(req: Request, res: Response, next: NextFunction) {
     const cronData = req.body;
-    const milvusAddress = (req.headers[MILVUS_ADDRESS] as string) || '';
+    const milvusAddress = (req.headers[MILVUS_CLIENT_ID] as string) || '';
     // console.log(cronData, milvusAddress);
     try {
       const result = await this.cronsService.toggleCronJobByName({

+ 15 - 15
server/src/crons/crons.service.ts

@@ -12,15 +12,15 @@ export class CronsService {
   async toggleCronJobByName(data: {
     name: string;
     type: WS_EVENTS_TYPE;
-    address: string;
+    milvusClientId: string;
   }) {
-    const { name, type, address } = data;
+    const { name, type, milvusClientId } = data;
 
     switch (name) {
       case WS_EVENTS.COLLECTION:
-        const cronJobEntity = this.schedulerRegistry.getCronJob(name, address);
+        const cronJobEntity = this.schedulerRegistry.getCronJob(name, milvusClientId);
         if (!cronJobEntity && Number(type) === WS_EVENTS_TYPE.START) {
-          return this.getCollections(WS_EVENTS.COLLECTION, address);
+          return this.getCollections(WS_EVENTS.COLLECTION, milvusClientId);
         }
         if (!cronJobEntity) {
           return;
@@ -33,7 +33,7 @@ export class CronsService {
     }
   }
 
-  async getCollections(name: string, address: string) {
+  async getCollections(name: string, milvusClientId: string) {
     const task = async () => {
       try {
         const res = await this.collectionService.getAllCollections();
@@ -46,7 +46,7 @@ export class CronsService {
         return res;
       } catch (error) {
         // When user not connect milvus, stop cron
-        const cronJobEntity = this.schedulerRegistry.getCronJob(name, address);
+        const cronJobEntity = this.schedulerRegistry.getCronJob(name, milvusClientId);
         if (cronJobEntity) {
           cronJobEntity.stop();
         }
@@ -54,23 +54,23 @@ export class CronsService {
         throw new Error(error);
       }
     };
-    this.schedulerRegistry.setCronJobEveryFiveSecond(name, task, address);
+    this.schedulerRegistry.setCronJobEveryFiveSecond(name, task, milvusClientId);
   }
 }
 
 export class SchedulerRegistry {
   constructor(private cronJobList: CronJob[]) {}
 
-  getCronJob(name: string, address: string) {
+  getCronJob(name: string, milvusClientId: string) {
     const target = this.cronJobList.find(
-      item => item.name === name && item.address === address
+      item => item.name === name && item.milvusClientId === milvusClientId
     );
     return target?.entity;
   }
 
-  setCronJobEveryFiveSecond(name: string, func: () => {}, address: string) {
+  setCronJobEveryFiveSecond(name: string, func: () => {}, milvusClientId: string) {
     // The cron job will run every second
-    this.setCronJob(name, '*/5 * * * * *', func, address);
+    this.setCronJob(name, '*/5 * * * * *', func, milvusClientId);
   }
 
   // ┌────────────── second (optional)
@@ -83,9 +83,9 @@ export class SchedulerRegistry {
   // │ │ │ │ │ │
   // * * * * * *
   // https://www.npmjs.com/package/node-cron
-  setCronJob(name: string, scheduler: string, func: () => {}, address: string) {
+  setCronJob(name: string, scheduler: string, func: () => {}, milvusClientId: string) {
     const target = this.cronJobList.find(
-      item => item.name === name && item.address === address
+      item => item.name === name && item.milvusClientId === milvusClientId
     );
     if (target) {
       target?.entity?.stop();
@@ -97,7 +97,7 @@ export class SchedulerRegistry {
       this.cronJobList.push({
         name,
         entity: task,
-        address,
+        milvusClientId,
       });
     }
   }
@@ -106,5 +106,5 @@ export class SchedulerRegistry {
 interface CronJob {
   name: string;
   entity: ScheduledTask;
-  address: string; // milvus address
+  milvusClientId: string; // milvus milvusClientId
 }

+ 1 - 2
server/src/database/databases.controller.ts

@@ -1,6 +1,5 @@
 import { NextFunction, Request, Response, Router } from 'express';
 import { dtoValidationMiddleware } from '../middleware/validation';
-import { milvusService } from '../milvus';
 import { DatabasesService } from './databases.service';
 import { CreateDatabaseDto } from './dto';
 
@@ -9,7 +8,7 @@ export class DatabasesController {
   private router: Router;
 
   constructor() {
-    this.databasesService = new DatabasesService(milvusService);
+    this.databasesService = new DatabasesService();
 
     this.router = Router();
   }

+ 3 - 5
server/src/database/databases.service.ts

@@ -7,22 +7,20 @@ import {
 import { throwErrorFromSDK } from '../utils/Error';
 
 export class DatabasesService {
-  constructor(private milvusService: MilvusService) { }
-
   async createDatabase(data: CreateDatabaseRequest) {
-    const res = await this.milvusService.client.createDatabase(data);
+    const res = await MilvusService.activeMilvusClient.createDatabase(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async listDatabase(data?: ListDatabasesRequest) {
-    const res = await this.milvusService.client.listDatabases(data);
+    const res = await MilvusService.activeMilvusClient.listDatabases(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async dropDatabase(data: DropDatabasesRequest) {
-    const res = await this.milvusService.client.dropDatabase(data);
+    const res = await MilvusService.activeMilvusClient.dropDatabase(data);
     throwErrorFromSDK(res);
     return res;
   }

+ 7 - 7
server/src/middleware/index.ts

@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express';
 import morgan from 'morgan';
 import chalk from 'chalk';
 import { MilvusService } from '../milvus/milvus.service';
-import { MILVUS_ADDRESS, HTTP_STATUS_CODE } from '../utils';
+import { MILVUS_CLIENT_ID, HTTP_STATUS_CODE } from '../utils';
 import { HttpError } from 'http-errors';
 import HttpErrors from 'http-errors';
 import { clientCache } from '../app';
@@ -14,23 +14,23 @@ export const ReqHeaderMiddleware = (
 ) => {
   // all ape requests need set milvus address in header.
   // server will set active address in milvus service.
-  const milvusAddress = (req.headers[MILVUS_ADDRESS] as string) || '';
+  const milvusClientId = (req.headers[MILVUS_CLIENT_ID] as string) || '';
 
   // console.log('------ Request headers -------', req.headers);
-  //  only api request has MILVUS_ADDRESS.
+  //  only api request has MILVUS_CLIENT_ID.
   //  When client run in express, we dont need static files like: xx.js run this logic.
   //  Otherwise will cause 401 error.
-  if (milvusAddress && clientCache.has(milvusAddress)) {
-    MilvusService.activeAddress = milvusAddress;
+  if (milvusClientId && clientCache.has(milvusClientId)) {
+    MilvusService.activeAddress = milvusClientId;
     // insight cache will update expire time when use insightCache.get
-    MilvusService.activeMilvusClient = clientCache.get(milvusAddress);
+    MilvusService.activeMilvusClient = clientCache.get(milvusClientId);
   }
 
   const CONNECT_URL = `/api/v1/milvus/connect`;
 
   if (
     req.url !== CONNECT_URL &&
-    milvusAddress &&
+    milvusClientId &&
     !MilvusService.activeMilvusClient
   ) {
     throw HttpErrors(

+ 7 - 7
server/src/milvus/milvus.service.ts

@@ -18,17 +18,13 @@ export class MilvusService {
   static activeMilvusClient: MilvusClient;
 
   constructor() {
-    this.databaseService = new DatabasesService(this);
+    this.databaseService = new DatabasesService();
   }
 
   get sdkInfo() {
     return MilvusClient.sdkInfo;
   }
 
-  get client() {
-    return MilvusService.activeMilvusClient;
-  }
-
   static formatAddress(address: string) {
     // remove http prefix from address
     const ip = address.replace(/(http):\/\//, '');
@@ -106,7 +102,7 @@ export class MilvusService {
 
       // If the server is healthy, set the active address and add the client to the cache
       MilvusService.activeAddress = address;
-      clientCache.set(address, milvusClient);
+      clientCache.set(milvusClient.clientId, milvusClient);
 
       // Create a new database service and check if the specified database exists
       let hasDatabase = false;
@@ -122,7 +118,11 @@ export class MilvusService {
       }
 
       // Return the address and the database (if it exists, otherwise return 'default')
-      return { address, database: hasDatabase ? database : 'default' };
+      return {
+        address,
+        database: hasDatabase ? database : 'default',
+        clientId: milvusClient.clientId,
+      };
     } catch (error) {
       // If any error occurs, clear the cache and throw the error
       clientCache.dump();

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

@@ -1,7 +1,6 @@
 import { NextFunction, Request, Response, Router } from 'express';
 import { dtoValidationMiddleware } from '../middleware/validation';
 import { PartitionsService } from './partitions.service';
-import { milvusService } from '../milvus';
 
 import {
   GetPartitionsInfoDto,
@@ -14,7 +13,7 @@ export class PartitionController {
   private partitionsService: PartitionsService;
 
   constructor() {
-    this.partitionsService = new PartitionsService(milvusService);
+    this.partitionsService = new PartitionsService();
     this.router = Router();
   }
 

+ 8 - 8
server/src/partitions/partitions.service.ts

@@ -12,8 +12,6 @@ import { findKeyValue } from '../utils/Helper';
 import { ROW_COUNT } from '../utils';
 
 export class PartitionsService {
-  constructor(private milvusService: MilvusService) {}
-
   async getPartitionsInfo(data: ShowPartitionsReq) {
     const result = [];
     const res = await this.getPartitions(data);
@@ -35,37 +33,39 @@ export class PartitionsService {
   }
 
   async getPartitions(data: ShowPartitionsReq) {
-    const res = await this.milvusService.client.showPartitions(data);
+    const res = await MilvusService.activeMilvusClient.showPartitions(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async createPartition(data: CreatePartitionReq) {
-    const res = await this.milvusService.client.createPartition(data);
+    const res = await MilvusService.activeMilvusClient.createPartition(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async deletePartition(data: DropPartitionReq) {
-    const res = await this.milvusService.client.dropPartition(data);
+    const res = await MilvusService.activeMilvusClient.dropPartition(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async getPartitionStatistics(data: GetPartitionStatisticsReq) {
-    const res = await this.milvusService.client.getPartitionStatistics(data);
+    const res = await MilvusService.activeMilvusClient.getPartitionStatistics(
+      data
+    );
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async loadPartitions(data: LoadPartitionsReq) {
-    const res = await this.milvusService.client.loadPartitions(data);
+    const res = await MilvusService.activeMilvusClient.loadPartitions(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async releasePartitions(data: ReleasePartitionsReq) {
-    const res = await this.milvusService.client.releasePartitions(data);
+    const res = await MilvusService.activeMilvusClient.releasePartitions(data);
     throwErrorFromSDK(res);
     return res;
   }

+ 1 - 2
server/src/schema/schema.controller.ts

@@ -1,7 +1,6 @@
 import { NextFunction, Request, Response, Router } from 'express';
 import { dtoValidationMiddleware } from '../middleware/validation';
 import { SchemaService } from './schema.service';
-import { milvusService } from '../milvus';
 import { ManageIndexDto } from './dto';
 
 export class SchemaController {
@@ -9,7 +8,7 @@ export class SchemaController {
   private schemaService: SchemaService;
 
   constructor() {
-    this.schemaService = new SchemaService(milvusService);
+    this.schemaService = new SchemaService();
     this.router = Router();
   }
 

+ 3 - 5
server/src/schema/schema.service.ts

@@ -9,10 +9,8 @@ import { MilvusService } from '../milvus/milvus.service';
 import { indexCache } from '../app';
 
 export class SchemaService {
-  constructor(private milvusService: MilvusService) {}
-
   async createIndex(data: CreateIndexReq) {
-    const res = await this.milvusService.client.createIndex(data);
+    const res = await MilvusService.activeMilvusClient.createIndex(data);
     const key = data.collection_name;
 
     // clear cache;
@@ -42,7 +40,7 @@ export class SchemaService {
       return value;
     } else {
       // If the index description is not in the cache, call the Milvus SDK's describeIndex function
-      const res = await this.milvusService.client.describeIndex(data);
+      const res = await MilvusService.activeMilvusClient.describeIndex(data);
 
       // If the index is finished building and there is at least one index description,
       // cache the index description for future use
@@ -62,7 +60,7 @@ export class SchemaService {
   }
 
   async dropIndex(data: DropIndexReq) {
-    const res = await this.milvusService.client.dropIndex(data);
+    const res = await MilvusService.activeMilvusClient.dropIndex(data);
     const key = data.collection_name;
 
     // clear cache;

+ 1 - 2
server/src/users/users.controller.ts

@@ -1,7 +1,6 @@
 import { NextFunction, Request, Response, Router } from 'express';
 import { dtoValidationMiddleware } from '../middleware/validation';
 import { UserService } from './users.service';
-import { milvusService } from '../milvus';
 import {
   CreateUserDto,
   UpdateUserDto,
@@ -15,7 +14,7 @@ export class UserController {
   private userService: UserService;
 
   constructor() {
-    this.userService = new UserService(milvusService);
+    this.userService = new UserService();
     this.router = Router();
   }
 

+ 16 - 16
server/src/users/users.service.ts

@@ -21,76 +21,74 @@ import {
 import { throwErrorFromSDK } from '../utils/Error';
 
 export class UserService {
-  constructor(private milvusService: MilvusService) {}
-
   async getUsers() {
-    const res = await this.milvusService.client.listUsers();
+    const res = await MilvusService.activeMilvusClient.listUsers();
     throwErrorFromSDK(res.status);
 
     return res;
   }
 
   async createUser(data: CreateUserReq) {
-    const res = await this.milvusService.client.createUser(data);
+    const res = await MilvusService.activeMilvusClient.createUser(data);
     throwErrorFromSDK(res);
 
     return res;
   }
 
   async updateUser(data: UpdateUserReq) {
-    const res = await this.milvusService.client.updateUser(data);
+    const res = await MilvusService.activeMilvusClient.updateUser(data);
     throwErrorFromSDK(res);
 
     return res;
   }
 
   async deleteUser(data: DeleteUserReq) {
-    const res = await this.milvusService.client.deleteUser(data);
+    const res = await MilvusService.activeMilvusClient.deleteUser(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async getRoles(data?: listRoleReq) {
-    const res = await this.milvusService.client.listRoles(data);
+    const res = await MilvusService.activeMilvusClient.listRoles(data);
     throwErrorFromSDK(res.status);
 
     return res;
   }
 
   async selectUser(data?: SelectUserReq) {
-    const res = await this.milvusService.client.selectUser(data);
+    const res = await MilvusService.activeMilvusClient.selectUser(data);
     throwErrorFromSDK(res.status);
 
     return res;
   }
 
   async createRole(data: CreateRoleReq) {
-    const res = await this.milvusService.client.createRole(data);
+    const res = await MilvusService.activeMilvusClient.createRole(data);
     throwErrorFromSDK(res);
 
     return res;
   }
 
   async deleteRole(data: DropRoleReq) {
-    const res = await this.milvusService.client.dropRole(data);
+    const res = await MilvusService.activeMilvusClient.dropRole(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async assignUserRole(data: AddUserToRoleReq) {
-    const res = await this.milvusService.client.addUserToRole(data);
+    const res = await MilvusService.activeMilvusClient.addUserToRole(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async unassignUserRole(data: RemoveUserFromRoleReq) {
-    const res = await this.milvusService.client.removeUserFromRole(data);
+    const res = await MilvusService.activeMilvusClient.removeUserFromRole(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async hasRole(data: HasRoleReq) {
-    const res = await this.milvusService.client.hasRole(data);
+    const res = await MilvusService.activeMilvusClient.hasRole(data);
     throwErrorFromSDK(res.status);
     return res;
   }
@@ -106,19 +104,21 @@ export class UserService {
   }
 
   async listGrants(data: ListGrantsReq) {
-    const res = await this.milvusService.client.listGrants(data);
+    const res = await MilvusService.activeMilvusClient.listGrants(data);
     throwErrorFromSDK(res.status);
     return res;
   }
 
   async grantRolePrivilege(data: OperateRolePrivilegeReq) {
-    const res = await this.milvusService.client.grantRolePrivilege(data);
+    const res = await MilvusService.activeMilvusClient.grantRolePrivilege(data);
     throwErrorFromSDK(res);
     return res;
   }
 
   async revokeRolePrivilege(data: OperateRolePrivilegeReq) {
-    const res = await this.milvusService.client.revokeRolePrivilege(data);
+    const res = await MilvusService.activeMilvusClient.revokeRolePrivilege(
+      data
+    );
     throwErrorFromSDK(res);
     return res;
   }

+ 1 - 1
server/src/utils/Const.ts

@@ -2,7 +2,7 @@
 export const ROW_COUNT = 'row_count';
 
 // use in req header
-export const MILVUS_ADDRESS = 'milvus-address';
+export const MILVUS_CLIENT_ID = 'milvus-client-id';
 
 // for lru cache
 export const CLIENT_CACHE = 'insight_cache';