-
Notifications
You must be signed in to change notification settings - Fork 95
Description
Sorry if this is already supported or has already been discussed, I wasn't able to find anything in the docs or in another GitHub issue. We have some APIs that support batching, but only if all of the inputs are uniform in some way. For example, you could have an image resizing API that supports batch resizing, but only if the desired dimensions are the same. We want to use java-dataloader for the batching and caching support, but handling these sorts of constraints ends up being a bit of a hassle. We get a batch of keys that might have mixed dimensions, so inside our load function we need to partition the keys, make multiple HTTP requests, and handle combining the futures and merging the data. Here is a simplified example of what this might involve:
public class ImageResizeDataLoader implements MappedBatchLoader<ImageResizeRequest, ImageResizeResponse> {
@Override
public CompletionStage<Map<ImageResizeRequest, ImageResizeResponse>> load(Set<ImageResizeRequest> keys) {
Multimap<ResizeDimensions, ImageResizeRequest> dimensionsToKeys = keys
.stream()
.collect(Multimaps.toMultimap(key -> key.resizeDimensions, Function.identity(), HashMultimap::create));
Map<ImageResizeRequest, ImageResizeResponse> results = new ConcurrentHashMap<>();
List<CompletableFuture<?>> futures = new ArrayList<>();
dimensionsToKeys.asMap().forEach((dimensions, batch) -> {
futures.add(doLoad(dimensions, batch).thenAccept(results::putAll));
});
return CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).thenApply(ignored -> results);
}
private CompletableFuture<Map<ImageResizeRequest, ImageResizeResponse>> doLoad(
ResizeDimensions dimensions,
Collection<ImageResizeRequest> batch
) {
HttpRequest request = HttpRequest
.newBuilder()
.setMethod(StandardHttpMethod.POST)
.setUri("https://myapi.com/resize")
.addQueryParam("width", dimensions.width)
.addQueryParam("height", dimensions.height)
.setBody(batch.stream().map(i -> i.imageUrl).collect(Collectors.toSet()))
.build();
// make request, handle response
return null;
}
public static class ResizeDimensions {
public int width;
public int height;
// equals/hashCode
}
public static class ImageResizeRequest {
public String imageUrl;
public ResizeDimensions resizeDimensions;
// equals/hashCode
}
public static class ImageResizeResponse {
public String resizedUrl;
}
}
Is there a simpler way to handle this that I'm missing?