diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-12-16 17:24:15 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2021-12-16 17:24:15 +0100 |
commit | 2f68e3741a0ec2317bd2b2a39e0eda00ce6ef281 (patch) | |
tree | 1031cdd3a75d8029fd9380222dee0c81aa4dec7c /vespa-feed-client-api/src/main | |
parent | 88932e068abbbcbd7b78bb4c5d75b722569fde6a (diff) |
Add helper method for synchronous use of feed client
Diffstat (limited to 'vespa-feed-client-api/src/main')
3 files changed, 99 insertions, 0 deletions
diff --git a/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/FeedClient.java b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/FeedClient.java index d463c611d6a..5e95990a078 100644 --- a/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/FeedClient.java +++ b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/FeedClient.java @@ -2,6 +2,7 @@ package ai.vespa.feed.client; import java.io.Closeable; +import java.util.List; import java.util.concurrent.CompletableFuture; /** @@ -37,6 +38,24 @@ public interface FeedClient extends Closeable { */ CompletableFuture<Result> remove(DocumentId documentId, OperationParameters params); + /** + * Waits for all feed operations to complete, either successfully or with exception. + * @throws MultiFeedException if any operation fails + * @return list of results with the same ordering as the {@code promises} parameter + * */ + static List<Result> await(List<CompletableFuture<Result>> promises) throws MultiFeedException { + return Helper.await(promises); + } + + /** + * Same as {@link #await(List)} except {@code promises} parameter is a vararg + * @see #await(List) + */ + @SafeVarargs + static List<Result> await(CompletableFuture<Result>... promises) throws MultiFeedException { + return Helper.await(promises); + } + /** Returns a snapshot of the stats for this feed client, such as requests made, and responses by status. */ OperationStats stats(); diff --git a/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/Helper.java b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/Helper.java new file mode 100644 index 00000000000..59c12077bef --- /dev/null +++ b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/Helper.java @@ -0,0 +1,42 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.feed.client; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.stream.Collectors; + +/** + * @author bjorncs + */ +class Helper { + + private Helper() {} + + @SafeVarargs + static List<Result> await(CompletableFuture<Result>... promises) throws MultiFeedException { + List<CompletableFuture<Result>> list = new ArrayList<>(); + for (CompletableFuture<Result> p : promises) list.add(p); + return await(list); + } + + static List<Result> await(List<CompletableFuture<Result>> promises) throws MultiFeedException { + try { + CompletableFuture.allOf(promises.toArray(new CompletableFuture<?>[0])).join(); + return promises.stream() + .map(p -> Objects.requireNonNull(p.getNow(null))) + .collect(Collectors.toList()); + } catch (CompletionException e) { + List<FeedException> exceptions = new ArrayList<>(); + for (CompletableFuture<Result> promise : promises) { + if (promise.isCompletedExceptionally()) { + // Lambda is executed on this thread since the future is already completed + promise.whenComplete((__, error) -> exceptions.add((FeedException) error)); + } + } + throw new MultiFeedException(exceptions); + } + } +} diff --git a/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/MultiFeedException.java b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/MultiFeedException.java new file mode 100644 index 00000000000..5db687b49ff --- /dev/null +++ b/vespa-feed-client-api/src/main/java/ai/vespa/feed/client/MultiFeedException.java @@ -0,0 +1,38 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.feed.client; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Aggregates multiple instances of {@link FeedException} + * + * @author bjorncs + */ +public class MultiFeedException extends RuntimeException { + + private final List<FeedException> exceptions; + + public MultiFeedException(Collection<FeedException> exceptions) { + super(toMessage(exceptions)); + this.exceptions = Collections.unmodifiableList(new ArrayList<>(exceptions)); + } + + public Collection<FeedException> feedExceptions() { return exceptions; } + + public Set<DocumentId> documentIds() { + return exceptions.stream() + .filter(e -> e.documentId().isPresent()) + .map(e -> e.documentId().get()) + .collect(Collectors.toSet()); + } + + private static String toMessage(Collection<FeedException> exceptions) { + return String.format("%d feed operations failed", exceptions.size()); + } + +} |