@@ -0,0 +1,1271 @@
+package ai.verta.modeldb.common.futures;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.List;%0Aimport java.util.concurrent.Executor;%0Aimport java.util.function.Function;%0Aimport java.util.stream.Collectors;%0A%0Apublic class BatchLoader%3CT, R%3E %7B%0A  private final Function%3CList%3CT%3E, InternalFuture%3CList%3CR%3E%3E%3E processor;%0A  private final Executor executor;%0A  private int maxBatchSize = 1000;%0A%0A  public BatchLoader(Function%3CList%3CT%3E, InternalFuture%3CList%3CR%3E%3E%3E processor, Executor executor) %7B%0A    this.processor = processor;%0A    this.executor = executor;%0A  %7D%0A%0A  public InternalFuture%3CList%3CR%3E%3E loadAll(List%3CT%3E ids) %7B%0A    if (ids.isEmpty()) return InternalFuture.completedInternalFuture(List.of());%0A%0A    var localList = new ArrayList%3CT%3E(maxBatchSize);%0A    var resultsList = new ArrayList%3CInternalFuture%3CList%3CR%3E%3E%3E();%0A    for (final var id : ids) %7B%0A      localList.add(id);%0A      if (localList.size() %3E= maxBatchSize) %7B%0A        resultsList.add(processor.apply(localList));%0A        localList = new ArrayList%3CT%3E(maxBatchSize);%0A      %7D%0A    %7D%0A    if (localList.size() %3E 0) %7B%0A      resultsList.add(processor.apply(localList));%0A    %7D%0A%0A    return InternalFuture.sequence(resultsList, executor)%0A        .thenApply(x -%3E x.stream().flatMap(y -%3E y.stream()).collect(Collectors.toList()), executor);%0A  %7D%0A%7D%0A

Add first version of the batch loader (#2537)