From be2329daa7cd6b08f4c00b99e774952f169b4c12 Mon Sep 17 00:00:00 2001 From: Dustin Kut Date: Mon, 14 Mar 2022 15:08:49 -0400 Subject: [PATCH] [NCL-6344] Implement Supplier interface (#603) Implement Supplier interface for `BuildFinder` and `DistributionAnalyzer`. This is useful when invoking both of them in a `CompletableFuture.supplyAsync` to produce a `CompletableFuture`. The latter can then be composed and combined with other `CompletableFuture`s. One reason for using that composability for NCL-6344 is to implement a cancellation feature. The flow goes from: url -> DistributionAnalyzer -> BuildFinder When running `DistributionAnalyzer` and `BuildFinder` as a future, it is really impossible to stop them in case of cancellation. However, we can cancel the rest of the flow after them. url -> future(DistributionAnalyzer) -> check if cancelled -> future(BuildFinder) Using a `CompletableFuture` makes this much easier. --- .../pnc/build/finder/core/BuildFinder.java | 22 ++++++++++++++++++- .../finder/core/DistributionAnalyzer.java | 22 ++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/jboss/pnc/build/finder/core/BuildFinder.java b/core/src/main/java/org/jboss/pnc/build/finder/core/BuildFinder.java index d644f0f8..1da4c22a 100644 --- a/core/src/main/java/org/jboss/pnc/build/finder/core/BuildFinder.java +++ b/core/src/main/java/org/jboss/pnc/build/finder/core/BuildFinder.java @@ -38,10 +38,12 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -70,7 +72,8 @@ import com.redhat.red.build.koji.model.xmlrpc.KojiTagInfo; import com.redhat.red.build.koji.model.xmlrpc.KojiTaskInfo; -public class BuildFinder implements Callable> { +public class BuildFinder + implements Callable>, Supplier> { private static final Logger LOGGER = LoggerFactory.getLogger(BuildFinder.class); private static final String BUILDS_FILENAME = "builds.json"; @@ -1203,6 +1206,23 @@ public Map call() throws KojiClientException { return allBuilds; } + /** + * Provide a Supplier version of the Callable. This is useful when using the BuildFinder to obtain a + * CompletableFuture (via {@link java.util.concurrent.CompletableFuture#supplyAsync(Supplier)}) + * + * throws CompletionException if a KojiClientException is thrown + * + * @return For each checksum type (key), the checksum values of the files + */ + @Override + public Map get() { + try { + return call(); + } catch (KojiClientException e) { + throw new CompletionException(e); + } + } + public void setListener(BuildFinderListener listener) { this.listener = listener; diff --git a/core/src/main/java/org/jboss/pnc/build/finder/core/DistributionAnalyzer.java b/core/src/main/java/org/jboss/pnc/build/finder/core/DistributionAnalyzer.java index 3e2ebaa5..786fe6de 100644 --- a/core/src/main/java/org/jboss/pnc/build/finder/core/DistributionAnalyzer.java +++ b/core/src/main/java/org/jboss/pnc/build/finder/core/DistributionAnalyzer.java @@ -39,12 +39,14 @@ import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; +import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -64,7 +66,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class DistributionAnalyzer implements Callable>> { +public class DistributionAnalyzer implements Callable>>, + Supplier>> { private static final Logger LOGGER = LoggerFactory.getLogger(DistributionAnalyzer.class); /** @@ -574,6 +577,23 @@ public Map> call() throws IOExce return Collections.unmodifiableMap(map); } + /** + * Provide a Supplier version of the Callable. This is useful when using the DistributionAnalyzer to obtain a + * CompletableFuture (via {@link java.util.concurrent.CompletableFuture#supplyAsync(Supplier)}) + * + * throws CompletionException if an IO exception is thrown + * + * @return For each checksum type (key), the checksum values of the files + */ + @Override + public Map> get() { + try { + return call(); + } catch (IOException e) { + throw new CompletionException(e); + } + } + public BlockingQueue getQueue() { return queue; }