@@ -38,6 +38,7 @@ protected ClientCache(String key, GenericKeyedObjectPool<String, T> pool) {
3838 @ Override
3939 public Thread newThread (@ NotNull Runnable r ) {
4040 Thread t = new Thread (r );
41+ t .setDaemon (true );
4142 t .setPriority (Thread .MAX_PRIORITY ); // set the highest priority for the timer
4243 return t ;
4344 }
@@ -49,24 +50,38 @@ public Thread newThread(@NotNull Runnable r) {
4950
5051 public void preparePool () {
5152 try {
52- // preparePool() will create minIdlePerKey MilvusClient objects in advance, put the pre-created clients
53- // into activeClientList
53+ // preparePool() will create minIdlePerKey MilvusClient objects in advance
5454 clientPool .preparePool (this .key );
55- int minIdlePerKey = clientPool .getMinIdlePerKey ();
56- for (int i = 0 ; i < minIdlePerKey ; i ++) {
57- activeClientList .add (new ClientWrapper <>(clientPool .borrowObject (this .key )));
58- }
55+ } catch (Exception e ) {
56+ logger .error ("Failed to prepare pool {}, exception: " , key , e );
57+ throw new MilvusClientException (ErrorCode .CLIENT_ERROR , e );
58+ }
59+
60+ // Put the pre-created clients into activeClientList
61+ // avoid borrow client from pool multiple times when multiple threads call preparePool() at the same time,
62+ // add a lock here since preparePool() is called only one time in practice, doesn't affect major performance
63+ int minIdlePerKey = clientPool .getMinIdlePerKey ();
5964
60- if (logger .isDebugEnabled ()) {
61- logger .debug ("ClientCache key: {} cache clients: {} " , key , activeClientList .size ());
62- logger .debug ("Pool initialize idle: {} active: {} " , clientPool .getNumIdle (key ), clientPool .getNumActive (key ));
65+ clientListLock .lock ();
66+ try {
67+ if (activeClientList .isEmpty ()) {
68+ for (int i = 0 ; i < minIdlePerKey ; i ++) {
69+ activeClientList .add (new ClientWrapper <>(clientPool .borrowObject (this .key )));
70+ }
6371 }
64- // System.out.printf("Key: %s, cache client: %d%n", key, activeClientList.size());
65- // System.out.printf("Pool idle %d, active %d%n", clientPool.getNumIdle(key), clientPool.getNumActive(key));
6672 } catch (Exception e ) {
67- logger .error ("Failed to prepare pool {}, exception: " , key , e );
73+ logger .error ("Failed to borrow client from pool {}, exception: " , key , e );
6874 throw new MilvusClientException (ErrorCode .CLIENT_ERROR , e );
75+ } finally {
76+ clientListLock .unlock ();
77+ }
78+
79+ if (logger .isDebugEnabled ()) {
80+ logger .debug ("ClientCache key: {} cache clients: {} " , key , activeClientList .size ());
81+ logger .debug ("Pool initialize idle: {} active: {} " , clientPool .getNumIdle (key ), clientPool .getNumActive (key ));
6982 }
83+ // System.out.printf("Key: %s, cache client: %d%n", key, activeClientList.size());
84+ // System.out.printf("Pool idle %d, active %d%n", clientPool.getNumIdle(key), clientPool.getNumActive(key));
7085 }
7186
7287 // this method is called in an interval, it does the following tasks:
@@ -161,7 +176,7 @@ private void checkQPS() {
161176 private void returnRetiredClients () {
162177 retireClientList .removeIf (wrapper -> {
163178 if (wrapper .getRefCount () <= 0 ) {
164- returnToPool (wrapper .getClient ());
179+ returnToPool (wrapper .getRawClient ());
165180
166181 if (logger .isDebugEnabled ()) {
167182 logger .debug ("ClientCache key: {} returns a client" , key );
@@ -188,7 +203,23 @@ public void run() {
188203 }
189204
190205 public void stopTimer () {
191- scheduler .shutdown ();
206+ // Stop scheduled tasks and wait for any in-flight checkQPS() execution to finish
207+ scheduler .shutdownNow ();
208+ try {
209+ scheduler .awaitTermination (5 , TimeUnit .SECONDS );
210+ } catch (InterruptedException e ) {
211+ Thread .currentThread ().interrupt ();
212+ }
213+
214+ // Return all active and retired clients to the pool so they can be properly destroyed
215+ for (ClientWrapper <T > wrapper : activeClientList ) {
216+ returnToPool (wrapper .getRawClient ());
217+ }
218+ activeClientList .clear ();
219+ for (ClientWrapper <T > wrapper : retireClientList ) {
220+ returnToPool (wrapper .getRawClient ());
221+ }
222+ retireClientList .clear ();
192223 }
193224
194225 public T getClient () {
@@ -323,6 +354,10 @@ public T getClient() {
323354 return this .client ;
324355 }
325356
357+ public T getRawClient () {
358+ return this .client ;
359+ }
360+
326361 public void returnClient () {
327362 this .refCount .decrementAndGet ();
328363 }
0 commit comments