1919import java .time .Instant ;
2020import java .util .ArrayList ;
2121import java .util .Arrays ;
22+ import java .util .Collection ;
2223import java .util .LinkedHashSet ;
2324import java .util .List ;
2425import java .util .Map ;
2728import java .util .concurrent .CompletableFuture ;
2829import java .util .concurrent .CompletionException ;
2930import java .util .concurrent .CompletionStage ;
31+ import java .util .concurrent .ConcurrentLinkedQueue ;
3032import java .util .concurrent .atomic .AtomicReference ;
3133
3234import static java .util .Collections .emptyList ;
@@ -329,17 +331,18 @@ private CompletableFuture<List<V>> dispatchQueueBatch(List<K> keys, List<Object>
329331 return CompletableFutureKit .success (values );
330332 }
331333
332- Runnable completeValuesRunnable = () -> {
333- List <K > clearCacheKeys = new ArrayList <>();
334- for (int idx = 0 ; idx < queuedFutures .size (); idx ++) {
335- K key = keys .get (idx );
336- V value = values .get (idx );
337- Object callContext = keyContexts .get (idx );
338- CompletableFuture <V > future = queuedFutures .get (idx );
334+ Collection <K > clearCacheKeys = new ConcurrentLinkedQueue <>();
335+ List <Runnable > completeValueRunnables = new ArrayList <>();
336+ for (int idx = 0 ; idx < queuedFutures .size (); idx ++) {
337+ K key = keys .get (idx );
338+ V value = values .get (idx );
339+ Object callContext = keyContexts .get (idx );
340+ CompletableFuture <V > future = queuedFutures .get (idx );
341+ Runnable completeValueRunnable = () -> {
339342 if (value instanceof Throwable ) {
340343 stats .incrementLoadErrorCount (new IncrementLoadErrorCountStatisticsContext <>(key , callContext ));
341344 future .completeExceptionally ((Throwable ) value );
342- clearCacheKeys .add (keys . get ( idx ) );
345+ clearCacheKeys .add (key );
343346 } else if (value instanceof Try ) {
344347 // we allow the batch loader to return a Try so we can better represent a computation
345348 // that might have worked or not.
@@ -349,16 +352,18 @@ private CompletableFuture<List<V>> dispatchQueueBatch(List<K> keys, List<Object>
349352 } else {
350353 stats .incrementLoadErrorCount (new IncrementLoadErrorCountStatisticsContext <>(key , callContext ));
351354 future .completeExceptionally (tryValue .getThrowable ());
352- clearCacheKeys .add (keys . get ( idx ) );
355+ clearCacheKeys .add (key );
353356 }
354357 } else {
355358 future .complete (value );
356359 }
357- }
360+ };
361+ completeValueRunnables .add (completeValueRunnable );
362+ }
363+ return scheduleCompletion (environment , keys , values , completeValueRunnables ).thenApply (ignored -> {
358364 possiblyClearCacheEntriesOnExceptions (clearCacheKeys );
359- };
360-
361- return scheduleCompletion (environment , keys , values , completeValuesRunnable );
365+ return values ;
366+ });
362367 }).exceptionally (ex -> {
363368 stats .incrementBatchLoadExceptionCount (new IncrementBatchLoadExceptionCountStatisticsContext <>(keys , keyContexts ));
364369 if (ex instanceof CompletionException ) {
@@ -375,14 +380,14 @@ private CompletableFuture<List<V>> dispatchQueueBatch(List<K> keys, List<Object>
375380 });
376381 }
377382
378- private CompletableFuture <List <V >> scheduleCompletion (BatchLoaderEnvironment environment , List <K > keys , List <V > values , Runnable completeValuesRunnable ) {
383+ private CompletableFuture <List <V >> scheduleCompletion (BatchLoaderEnvironment environment , List <K > keys , List <V > values , List < Runnable > completeValueRunnables ) {
379384 BatchLoaderScheduler batchLoaderScheduler = loaderOptions .getBatchLoaderScheduler ();
380385 CompletionStage <?> scheduledCompletion ;
381386 if (batchLoaderScheduler != null ) {
382387 scheduledCompletion = batchLoaderScheduler
383- .scheduleCompletion (completeValuesRunnable , keys , environment );
388+ .scheduleCompletion (completeValueRunnables , keys , environment );
384389 } else {
385- scheduledCompletion = CompletableFutureKit .run ( completeValuesRunnable );
390+ scheduledCompletion = CompletableFutureKit .runAll ( completeValueRunnables );
386391 }
387392 return scheduledCompletion
388393 .thenApply (ignored -> values )
@@ -400,7 +405,7 @@ private void assertResultSize(List<K> keys, List<V> values) {
400405 assertState (keys .size () == values .size (), () -> "The size of the promised values MUST be the same size as the key list" );
401406 }
402407
403- private void possiblyClearCacheEntriesOnExceptions (List <K > keys ) {
408+ private void possiblyClearCacheEntriesOnExceptions (Collection <K > keys ) {
404409 if (keys .isEmpty ()) {
405410 return ;
406411 }
0 commit comments