Skip to content

Commit ed7debc

Browse files
authored
Refine code (#1683)
Signed-off-by: yhmo <yihua.mo@zilliz.com>
1 parent cd62001 commit ed7debc

File tree

4 files changed

+143
-138
lines changed

4 files changed

+143
-138
lines changed

sdk-core/src/main/java/io/milvus/orm/iterator/SearchIteratorV2.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ public List<SearchResp.SearchResult> next() {
186186
}
187187

188188
// create a list with elements from 0 to targetLen, and remove the elements from cache
189+
targetLen = Math.min(cache.size(), targetLen);
189190
List<SearchResp.SearchResult> subList = cache.subList(0, targetLen);
190191
List<SearchResp.SearchResult> ret = new ArrayList<>(subList);
191192
subList.clear();

sdk-core/src/main/java/io/milvus/v2/client/MilvusClientV2.java

Lines changed: 3 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import io.milvus.orm.iterator.QueryIterator;
2828
import io.milvus.orm.iterator.SearchIterator;
2929
import io.milvus.orm.iterator.SearchIteratorV2;
30-
import io.milvus.v2.exception.ErrorCode;
31-
import io.milvus.v2.exception.MilvusClientException;
3230
import io.milvus.v2.service.cdc.CDCService;
3331
import io.milvus.v2.service.cdc.request.UpdateReplicateConfigurationReq;
3432
import io.milvus.v2.service.cdc.response.UpdateReplicateConfigurationResp;
@@ -71,19 +69,6 @@
7169

7270
import java.util.List;
7371
import java.util.concurrent.TimeUnit;
74-
import java.net.InetAddress;
75-
import java.net.UnknownHostException;
76-
import java.net.Socket;
77-
import java.io.IOException;
78-
import java.net.InetSocketAddress;
79-
import javax.net.ssl.*;
80-
import java.io.FileInputStream;
81-
import java.io.InputStream;
82-
import java.security.KeyStore;
83-
import java.security.PrivateKey;
84-
import java.security.SecureRandom;
85-
import java.security.cert.CertificateFactory;
86-
import java.security.cert.X509Certificate;
8772

8873
public class MilvusClientV2 {
8974
private static final Logger logger = LoggerFactory.getLogger(MilvusClientV2.class);
@@ -140,9 +125,9 @@ private void initServices(String dbName) {
140125
private void connect(ConnectConfig connectConfig) {
141126
this.connectConfig = connectConfig;
142127
if (connectConfig.isEnablePrecheck()) {
143-
validateHostname(connectConfig);
144-
validatePort(connectConfig);
145-
validateCert(connectConfig);
128+
clientUtils.validateHostname(connectConfig);
129+
clientUtils.validatePort(connectConfig);
130+
clientUtils.validateCert(connectConfig);
146131
}
147132
try {
148133
if (this.channel != null) {
@@ -235,120 +220,6 @@ public String currentUsedDatabase() {
235220
return dbName;
236221
}
237222

238-
/**
239-
* Validates that the hostname can be resolved before attempting connection.
240-
* This provides early failure with clear error messages for DNS issues.
241-
*
242-
* @param connectConfig Connection configuration containing the host to validate
243-
* @throws MilvusClientException if hostname cannot be resolved
244-
*/
245-
public void validateHostname(ConnectConfig connectConfig) {
246-
String host = connectConfig.getHost();
247-
248-
if (StringUtils.isEmpty(host)) {
249-
throw new MilvusClientException(ErrorCode.INVALID_PARAMS,
250-
"Hostname cannot be null or empty");
251-
}
252-
253-
try {
254-
// Attempt DNS resolution
255-
InetAddress.getByName(host);
256-
logger.debug("Successfully resolved hostname: {}", host);
257-
} catch (UnknownHostException e) {
258-
String message = String.format(
259-
"Failed to resolve hostname '%s'. Please verify the hostname is correct and DNS is configured properly.",
260-
host
261-
);
262-
logger.error(message, e);
263-
throw new MilvusClientException(ErrorCode.RPC_ERROR, message);
264-
}
265-
}
266-
267-
/**
268-
* Validates port number and tests connectivity.
269-
*
270-
* @param connectConfig Connection configuration containing the port to validate
271-
* @throws MilvusClientException if port is invalid or unreachable
272-
*/
273-
public void validatePort(ConnectConfig connectConfig) {
274-
int port = connectConfig.getPort();
275-
String host = connectConfig.getHost();
276-
277-
// Check valid range
278-
if (port < 1 || port > 65535) {
279-
String message = String.format(
280-
"Invalid port number '%d'. Port must be between 1 and 65535.",
281-
port
282-
);
283-
logger.error(message);
284-
throw new MilvusClientException(ErrorCode.INVALID_PARAMS, message);
285-
}
286-
287-
// Test if port is reachable
288-
try (Socket socket = new Socket()) {
289-
socket.connect(new InetSocketAddress(host, port), (int) connectConfig.getConnectTimeoutMs());
290-
logger.debug("Successfully validated port: {}", port);
291-
} catch (IOException e) {
292-
String message = String.format(
293-
"Cannot connect to '%s:%d'. Please verify the port number is correct and server is running.",
294-
host, port
295-
);
296-
logger.error(message, e);
297-
throw new MilvusClientException(ErrorCode.RPC_ERROR, message);
298-
}
299-
}
300-
301-
/**
302-
* Validates SSL connection with certificates.
303-
*
304-
* @param connectConfig Connection configuration
305-
* @throws MilvusClientException if SSL connection fails
306-
*/
307-
public void validateCert(ConnectConfig connectConfig) {
308-
if (!connectConfig.isSecure()) {
309-
return;
310-
}
311-
312-
try {
313-
SSLContext sslContext = SSLContext.getInstance("TLS");
314-
TrustManagerFactory tmf = null;
315-
316-
// Load server certificate (CA cert)
317-
if (connectConfig.getServerPemPath() != null && !connectConfig.getServerPemPath().isEmpty()) {
318-
try (InputStream certStream = new FileInputStream(connectConfig.getServerPemPath())) {
319-
CertificateFactory cf = CertificateFactory.getInstance("X.509");
320-
X509Certificate caCert = (X509Certificate) cf.generateCertificate(certStream);
321-
322-
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
323-
trustStore.load(null, null);
324-
trustStore.setCertificateEntry("ca-cert", caCert);
325-
326-
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
327-
tmf.init(trustStore);
328-
}
329-
}
330-
331-
// Initialize SSLContext with the server certificate
332-
sslContext.init(null, tmf != null ? tmf.getTrustManagers() : null, new SecureRandom());
333-
334-
// Validate connection
335-
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
336-
try (SSLSocket socket = (SSLSocket) socketFactory.createSocket()) {
337-
socket.connect(new InetSocketAddress(connectConfig.getHost(), connectConfig.getPort()),
338-
(int) connectConfig.getConnectTimeoutMs());
339-
socket.startHandshake();
340-
logger.debug("SSL certificate validation passed");
341-
}
342-
343-
} catch (SSLException e) {
344-
throw new MilvusClientException(ErrorCode.RPC_ERROR,
345-
"SSL certificate validation failed: " + e.getMessage() +
346-
". Please verify your certificates are correct.");
347-
} catch (Exception e) {
348-
throw new MilvusClientException(ErrorCode.RPC_ERROR,
349-
"Failed to connect with SSL: " + e.getMessage());
350-
}
351-
}
352223

353224
/////////////////////////////////////////////////////////////////////////////////////////////
354225
// Database Operations

sdk-core/src/main/java/io/milvus/v2/exception/MilvusClientException.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,16 @@ public int getServerErrCode() {
5555
public int getLegacyServerCode() {
5656
return legacyServerCode;
5757
}
58+
59+
@Override
60+
public String toString() {
61+
String s = super.toString();
62+
String codeMsg = " ErrorCode: " + errorCode.name();
63+
if (serverErrCode > 0) {
64+
codeMsg += (", ServerCode: " + serverErrCode);
65+
} else if (legacyServerCode > 0) {
66+
codeMsg += (", ServerCode: " + legacyServerCode);
67+
}
68+
return s + codeMsg;
69+
}
5870
}

sdk-core/src/main/java/io/milvus/v2/utils/ClientUtils.java

Lines changed: 127 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,23 @@
2727
import io.milvus.client.MilvusServiceClient;
2828
import io.milvus.grpc.*;
2929
import io.milvus.v2.client.ConnectConfig;
30+
import io.milvus.v2.exception.ErrorCode;
31+
import io.milvus.v2.exception.MilvusClientException;
3032
import org.apache.commons.lang3.StringUtils;
3133
import org.slf4j.Logger;
3234
import org.slf4j.LoggerFactory;
3335

36+
import javax.net.ssl.*;
3437
import java.io.File;
38+
import java.io.FileInputStream;
3539
import java.io.IOException;
36-
import java.net.InetAddress;
37-
import java.net.InetSocketAddress;
38-
import java.net.SocketAddress;
39-
import java.net.UnknownHostException;
40+
import java.io.InputStream;
41+
import java.net.*;
4042
import java.nio.charset.StandardCharsets;
43+
import java.security.KeyStore;
44+
import java.security.SecureRandom;
45+
import java.security.cert.CertificateFactory;
46+
import java.security.cert.X509Certificate;
4147
import java.time.LocalDateTime;
4248
import java.util.ArrayList;
4349
import java.util.Base64;
@@ -188,8 +194,8 @@ public void start(ClientCall.Listener<RespT> responseListener, Metadata headers)
188194
/**
189195
* Configures the proxy settings for a NettyChannelBuilder if proxy address is specified
190196
*
191-
* @param builder NettyChannelBuilder to configure
192-
* @param connectConfig Connection configuration containing proxy settings
197+
* @param builder NettyChannelBuilder to configure
198+
* @param proxyAddress proxy address
193199
*/
194200
public static void configureProxy(ManagedChannelBuilder builder, String proxyAddress) {
195201
String[] hostPort = proxyAddress.split(":");
@@ -255,4 +261,119 @@ public String getSDKVersion() {
255261
}
256262
return ver;
257263
}
264+
265+
/**
266+
* Validates that the hostname can be resolved before attempting connection.
267+
* This provides early failure with clear error messages for DNS issues.
268+
*
269+
* @param connectConfig Connection configuration containing the host to validate
270+
* @throws MilvusClientException if hostname cannot be resolved
271+
*/
272+
public void validateHostname(ConnectConfig connectConfig) {
273+
String host = connectConfig.getHost();
274+
275+
if (StringUtils.isEmpty(host)) {
276+
throw new MilvusClientException(io.milvus.v2.exception.ErrorCode.INVALID_PARAMS,
277+
"Hostname cannot be null or empty");
278+
}
279+
280+
try {
281+
// Attempt DNS resolution
282+
InetAddress.getByName(host);
283+
logger.debug("Successfully resolved hostname: {}", host);
284+
} catch (UnknownHostException e) {
285+
String message = String.format(
286+
"Failed to resolve hostname '%s'. Please verify the hostname is correct and DNS is configured properly.",
287+
host
288+
);
289+
logger.error(message, e);
290+
throw new MilvusClientException(io.milvus.v2.exception.ErrorCode.RPC_ERROR, message);
291+
}
292+
}
293+
294+
/**
295+
* Validates port number and tests connectivity.
296+
*
297+
* @param connectConfig Connection configuration containing the port to validate
298+
* @throws MilvusClientException if port is invalid or unreachable
299+
*/
300+
public void validatePort(ConnectConfig connectConfig) {
301+
int port = connectConfig.getPort();
302+
String host = connectConfig.getHost();
303+
304+
// Check valid range
305+
if (port < 1 || port > 65535) {
306+
String message = String.format(
307+
"Invalid port number '%d'. Port must be between 1 and 65535.",
308+
port
309+
);
310+
logger.error(message);
311+
throw new MilvusClientException(io.milvus.v2.exception.ErrorCode.INVALID_PARAMS, message);
312+
}
313+
314+
// Test if port is reachable
315+
try (Socket socket = new Socket()) {
316+
socket.connect(new InetSocketAddress(host, port), (int) connectConfig.getConnectTimeoutMs());
317+
logger.debug("Successfully validated port: {}", port);
318+
} catch (IOException e) {
319+
String message = String.format(
320+
"Cannot connect to '%s:%d'. Please verify the port number is correct and server is running.",
321+
host, port
322+
);
323+
logger.error(message, e);
324+
throw new MilvusClientException(io.milvus.v2.exception.ErrorCode.RPC_ERROR, message);
325+
}
326+
}
327+
328+
/**
329+
* Validates SSL connection with certificates.
330+
*
331+
* @param connectConfig Connection configuration
332+
* @throws MilvusClientException if SSL connection fails
333+
*/
334+
public void validateCert(ConnectConfig connectConfig) {
335+
if (!connectConfig.isSecure()) {
336+
return;
337+
}
338+
339+
try {
340+
SSLContext sslContext = SSLContext.getInstance("TLS");
341+
TrustManagerFactory tmf = null;
342+
343+
// Load server certificate (CA cert)
344+
if (connectConfig.getServerPemPath() != null && !connectConfig.getServerPemPath().isEmpty()) {
345+
try (InputStream certStream = new FileInputStream(connectConfig.getServerPemPath())) {
346+
CertificateFactory cf = CertificateFactory.getInstance("X.509");
347+
X509Certificate caCert = (X509Certificate) cf.generateCertificate(certStream);
348+
349+
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
350+
trustStore.load(null, null);
351+
trustStore.setCertificateEntry("ca-cert", caCert);
352+
353+
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
354+
tmf.init(trustStore);
355+
}
356+
}
357+
358+
// Initialize SSLContext with the server certificate
359+
sslContext.init(null, tmf != null ? tmf.getTrustManagers() : null, new SecureRandom());
360+
361+
// Validate connection
362+
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
363+
try (SSLSocket socket = (SSLSocket) socketFactory.createSocket()) {
364+
socket.connect(new InetSocketAddress(connectConfig.getHost(), connectConfig.getPort()),
365+
(int) connectConfig.getConnectTimeoutMs());
366+
socket.startHandshake();
367+
logger.debug("SSL certificate validation passed");
368+
}
369+
370+
} catch (SSLException e) {
371+
throw new MilvusClientException(io.milvus.v2.exception.ErrorCode.RPC_ERROR,
372+
"SSL certificate validation failed: " + e.getMessage() +
373+
". Please verify your certificates are correct.");
374+
} catch (Exception e) {
375+
throw new MilvusClientException(ErrorCode.RPC_ERROR,
376+
"Failed to connect with SSL: " + e.getMessage());
377+
}
378+
}
258379
}

0 commit comments

Comments
 (0)