Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace axios with node-fetch #254

Merged
merged 9 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ module.exports = {
testTimeout: 60000,
// because user will cause other test fail, but we still have user spec
coveragePathIgnorePatterns: ['/milvus/User.ts'],
testPathIgnorePatterns: [
'cloud.spec.ts',
'serverless.spec.ts',
], // add this line
testPathIgnorePatterns: ['cloud.spec.ts', 'serverless.spec.ts'], // add this line
testEnvironmentOptions: {
NODE_ENV: 'production',
},
Expand Down
103 changes: 62 additions & 41 deletions milvus/HttpClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios, { AxiosInstance } from 'axios';
import fetch from 'node-fetch';
import { HttpClientConfig } from './types';
import { Collection, Vector } from './http';
import {
Expand All @@ -12,45 +12,9 @@ export class HttpBaseClient {
// The client configuration.
public config: HttpClientConfig;

// axios
public client: AxiosInstance;

constructor(config: HttpClientConfig) {
shanghaikid marked this conversation as resolved.
Show resolved Hide resolved
// Assign the configuration object.
this.config = config;

// setup axios client
this.client = axios.create({
baseURL: this.baseURL,
timeout: this.timeout,
timeoutErrorMessage: '',
withCredentials: true,
headers: {
Authorization: this.authorization,
Accept: 'application/json',
ContentType: 'application/json',
},
});

// interceptors
this.client.interceptors.request.use(request => {
// if dbName is not set, using default database
// GET
if (request.params) {
request.params.dbName = request.params.dbName || this.database;
}
// POST
if (request.data) {
request.data.dbName = request.data.dbName || this.database;
request.data = JSON.stringify(request.data);
}

// console.log('request: ', request.data);
return request;
});
this.client.interceptors.response.use(response => {
return response.data;
});
}

// baseURL
Expand Down Expand Up @@ -84,12 +48,69 @@ export class HttpBaseClient {
return this.config.timeout || DEFAULT_HTTP_TIMEOUT;
}

get POST() {
return this.client.post;
get headers() {
return {
Authorization: this.authorization,
Accept: 'application/json',
ContentType: 'application/json',
};
}

get GET() {
return this.client.get;
async POST<T>(url: string, data: Record<string, any> = {}): Promise<T> {
try {
// timeout controller
const controller = new AbortController();
shanghaikid marked this conversation as resolved.
Show resolved Hide resolved
const id = setTimeout(() => controller.abort(), this.timeout);

// assign data
if (data) {
data.dbName = data.dbName || this.database;
shanghaikid marked this conversation as resolved.
Show resolved Hide resolved
}

const response = await fetch(`${this.baseURL}${url}`, {
method: 'post',
headers: this.headers,
body: JSON.stringify(data),
signal: controller.signal,
});

clearTimeout(id);
return response.json() as T;
shanghaikid marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
if (error.name === 'AbortError') {
console.log('request was timeout');
}
return Promise.reject(error);
}
}

async GET<T>(url: string, params: Record<string, any> = {}): Promise<T> {
try {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), this.timeout);

// assign data
if (params) {
params.dbName = params.dbName || this.database;
}

const queryParams = new URLSearchParams(params);

const response = await fetch(`${this.baseURL}${url}?${queryParams}`, {
method: 'get',
headers: this.headers,
signal: controller.signal,
});

clearTimeout(id);

return response.json() as T;
} catch (error) {
if (error.name === 'AbortError') {
console.log('request was timeout');
}
return Promise.reject(error);
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions milvus/MilvusClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
CreateCollectionReq,
ERROR_REASONS,
checkCreateCollectionCompatibility,
DEFAULT_PRIMARY_KEY_FIELD,
DEFAULT_METRIC_TYPE,
DEFAULT_VECTOR_FIELD,
} from '.';
import sdkInfo from '../sdk.json';

Expand Down Expand Up @@ -91,10 +94,10 @@ export class MilvusClient extends GRPCClient {
const {
collection_name,
dimension,
primary_field_name = 'id',
primary_field_name = DEFAULT_PRIMARY_KEY_FIELD,
id_type = DataType.Int64,
metric_type = 'IP',
vector_field_name = 'vector',
metric_type = DEFAULT_METRIC_TYPE,
vector_field_name = DEFAULT_VECTOR_FIELD,
enableDynamicField = true,
enable_dynamic_field = true,
auto_id = false,
Expand Down
4 changes: 3 additions & 1 deletion milvus/const/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export const DEFAULT_DEBUG = false;
export const DEFAULT_MILVUS_PORT = 19530; // default milvus port
export const DEFAULT_CONNECT_TIMEOUT = 15 * 1000; // 15s
export const DEFAULT_TOPK = 100; // default topk
export const DEFAULT_METRIC_TYPE = 'L2';
export const DEFAULT_METRIC_TYPE = 'IP';
export const DEFAULT_VECTOR_FIELD = 'vector';
export const DEFAULT_PRIMARY_KEY_FIELD = 'id';
export const DEFAULT_MAX_RETRIES = 3; // max retry time
export const DEFAULT_RETRY_DELAY = 30; // retry delay, 30ms
export const DEFAULT_PARTITIONS_NUMBER = 64;
Expand Down
19 changes: 15 additions & 4 deletions milvus/http/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import {
HttpBaseResponse,
HttpBaseReq,
} from '../types';
import {
DEFAULT_PRIMARY_KEY_FIELD,
DEFAULT_METRIC_TYPE,
DEFAULT_VECTOR_FIELD,
} from '../const';

export function Collection<T extends Constructor<HttpBaseClient>>(Base: T) {
return class extends Base {
Expand All @@ -16,22 +21,28 @@ export function Collection<T extends Constructor<HttpBaseClient>>(Base: T) {
data: HttpCollectionCreateReq
): Promise<HttpBaseResponse> {
const url = `/vector/collections/create`;
return await this.POST(url, data);

// if some keys not provided, using default value
data.metricType = data.metricType || DEFAULT_METRIC_TYPE;
data.primaryField = data.primaryField || DEFAULT_PRIMARY_KEY_FIELD;
data.vectorField = data.vectorField || DEFAULT_VECTOR_FIELD;

return await this.POST<HttpBaseResponse>(url, data);
}

// GET describe collection
async describeCollection(
params: HttpBaseReq
): Promise<HttpCollectionDescribeResponse> {
const url = `/vector/collections/describe`;
return await this.GET(url, { params });
return await this.GET<HttpCollectionDescribeResponse>(url, params);
}

// POST drop collection
async dropCollection(data: HttpBaseReq): Promise<HttpBaseResponse> {
const url = `/vector/collections/drop`;

return await this.POST(url, data);
return await this.POST<HttpBaseResponse>(url, data);
}

// GET list collections
Expand All @@ -40,7 +51,7 @@ export function Collection<T extends Constructor<HttpBaseClient>>(Base: T) {
): Promise<HttpCollectionListResponse> {
const url = `/vector/collections`;

return await this.GET(url, { params });
return await this.GET<HttpCollectionListResponse>(url, params);
}
};
}
16 changes: 11 additions & 5 deletions milvus/http/Vector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,37 @@ export function Vector<T extends Constructor<HttpBaseClient>>(Base: T) {
// GET get data
async get(params: HttpVectorGetReq): Promise<HttpBaseResponse> {
const url = `/vector/get`;
return await this.GET(url, { params });
return await this.GET<HttpBaseResponse>(url, params);
}

// POST insert data
async insert(data: HttpVectorInsertReq): Promise<HttpVectorInsertResponse> {
const url = `/vector/insert`;
return await this.POST(url, data);
return await this.POST<HttpVectorInsertResponse>(url, data);
}

// POST insert data
async upsert(data: HttpVectorInsertReq): Promise<HttpVectorInsertResponse> {
const url = `/vector/insert`;
return await this.POST<HttpVectorInsertResponse>(url, data);
}

// POST query data
async query(data: HttpVectorQueryReq): Promise<HttpVectorQueryResponse> {
const url = `/vector/query`;
return await this.client.post(url, data);
return await this.POST<HttpVectorQueryResponse>(url, data);
}

// POST search data
async search(data: HttpVectorSearchReq): Promise<HttpVectorSearchResponse> {
const url = `/vector/search`;
return await this.POST(url, data);
return await this.POST<HttpVectorSearchResponse>(url, data);
}

// POST delete collection
async delete(data: HttpVectorDeleteReq): Promise<HttpBaseResponse> {
const url = `/vector/delete`;
return await this.POST(url, data);
return await this.POST<HttpBaseResponse>(url, data);
}
};
}
6 changes: 3 additions & 3 deletions milvus/types/Http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ export interface HttpBaseResponse<T = {}> {
// collection operations
export interface HttpCollectionCreateReq extends HttpBaseReq {
dimension: number;
metricType: string;
primaryField: string;
vectorField: string;
metricType?: string;
primaryField?: string;
vectorField?: string;
description?: string;
}
// list collection request
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"pre": "git submodule update --remote && rm -rf proto/proto/google && mkdir -p proto/proto/google/protobuf && wget https://raw.githubusercontent.com/protocolbuffers/protobuf/main/src/google/protobuf/descriptor.proto -O proto/proto/google/protobuf/descriptor.proto",
"build": "rm -rf dist && tsc --declaration && node build.js",
"test": "NODE_ENV=dev jest",
"test-cloud": "NODE_ENV=dev jest test/http --testPathIgnorePatterns=none",
"bench": "ts-node test/tools/bench.ts",
"coverage": "NODE_ENV=dev jest --coverage=true --config jest.config.js --no-cache",
"build-test": " yarn build && NODE_ENV=dev jest test/build/Collection.spec.ts --testPathIgnorePatterns=none",
Expand All @@ -21,15 +22,16 @@
"dependencies": {
"@grpc/grpc-js": "1.8.17",
"@grpc/proto-loader": "0.7.7",
"axios": "^1.5.1",
"dayjs": "^1.11.7",
"lru-cache": "^9.1.2",
"node-fetch": "2",
"protobufjs": "7.2.4",
"winston": "^3.9.0"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.21.5",
"@types/jest": "^29.5.1",
"@types/node-fetch": "^2.6.7",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
Expand Down
Loading