diff --git a/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/processor/DefaultProcessor.java b/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/processor/DefaultProcessor.java index 7c920f04a..aab267dbc 100644 --- a/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/processor/DefaultProcessor.java +++ b/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/processor/DefaultProcessor.java @@ -207,7 +207,12 @@ private boolean hasAnyHash(Optional sha256, Optional sha1, Optio } protected void processBrewBuild(Component component, Artifact artifact) { - KojiBuild brewBuild = kojiService.findBuild(artifact); + KojiBuild brewBuild = null; + try { + brewBuild = kojiService.findBuild(artifact); + } catch (Throwable e) { + log.error("Lookup in Brew failed due to {}", e.getMessage() == null ? e.toString() : e.getMessage(), e); + } if (brewBuild != null) { log.debug( diff --git a/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/service/KojiService.java b/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/service/KojiService.java index ce72e2583..b252b03fd 100644 --- a/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/service/KojiService.java +++ b/cli/src/main/java/org/jboss/sbomer/cli/feature/sbom/service/KojiService.java @@ -26,16 +26,20 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import org.apache.commons.collections4.MultiValuedMap; import org.eclipse.microprofile.context.ManagedExecutor; +import org.eclipse.microprofile.faulttolerance.Retry; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.jboss.pnc.build.finder.core.BuildConfig; import org.jboss.pnc.build.finder.core.BuildFinder; @@ -69,6 +73,9 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import static org.jboss.sbomer.core.rest.faulttolerance.Constants.KOJI_SERVICE_DELAY; +import static org.jboss.sbomer.core.rest.faulttolerance.Constants.KOJI_SERVICE_MAX_RETRIES; + /** * A service to interact with the Koji (Brew) build system. */ @@ -76,7 +83,7 @@ @ApplicationScoped public class KojiService { - private static final Long MAX_BREW_WAIT_5_MIN = 5 * 60 * 1000L; + private static final int MAX_BREW_WAIT_MIN = 5; private static final KojiObjectMapper MAPPER = new KojiObjectMapper(); public static final String REMOTE_SOURCE_PREFIX = "remote-source"; public static final String REMOTE_SOURCE_DELIMITER = "-"; @@ -109,7 +116,7 @@ public class KojiService { * @return Results of the analysis if the whole operation was successful. * @throws Throwable Thrown in case of any errors during the analysis */ - public List find( + private List find( String url, DistributionAnalyzerListener distributionAnalyzerListener, BuildFinderListener buildFinderListener) throws Throwable { @@ -122,12 +129,7 @@ public List find( } }); - try { - return awaitResults(finderTask); - } catch (InterruptedException | ExecutionException e) { // NOSONAR We are rethrowing it. - log.debug("Analysis failed due to {}", e.getMessage(), e); - throw e.getCause(); - } + return awaitResults(finderTask); } /** @@ -177,56 +179,48 @@ private List find( return brewBuilds; } - private List awaitResults(Future> finderTask) - throws InterruptedException, ExecutionException { - - int retry = 1; - while (!finderTask.isDone() && (retry * 500L) < MAX_BREW_WAIT_5_MIN) { - try { - retry++; - // FIXME: Call to 'Thread.sleep()' in a loop, probably busy-waiting - Thread.sleep(500); - } catch (InterruptedException e) { - log.warn("Sleeping while awaiting results was interrupted", e); - Thread.currentThread().interrupt(); - } - } - if (finderTask.isDone()) { - return finderTask.get(); + private List awaitResults(Future> finderTask) throws Throwable { + try { + return finderTask.get(MAX_BREW_WAIT_MIN, TimeUnit.MINUTES); + } catch (TimeoutException e) { + log.debug("Timeout waiting for build results"); + return Collections.emptyList(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return Collections.emptyList(); + } catch (ExecutionException e) { // NOSONAR We are rethrowing it. + log.debug("Analysis failed due to {}", e.getMessage(), e); + throw e.getCause(); } - return Collections.emptyList(); } - public KojiBuild findBuild(Artifact artifact) { - + @Retry(maxRetries = KOJI_SERVICE_MAX_RETRIES, delay = KOJI_SERVICE_DELAY, delayUnit = ChronoUnit.SECONDS) + public KojiBuild findBuild(Artifact artifact) throws Throwable { if (artifact.getPublicUrl() == null) { return null; } - try { - FinderStatus status = new FinderStatus(); - log.trace("Searching for artifact '{}' in Brew...", artifact.getPublicUrl()); - List brewBuilds = find(artifact.getPublicUrl(), status, status); - if (brewBuilds.size() == 1) { - log.trace( - "Found Brew build with id {} of artifact: '{}'", - brewBuilds.get(0).getId(), - artifact.getPublicUrl()); - return brewBuilds.get(0); - } else if (brewBuilds.size() > 1) { - String brewBuildIds = brewBuilds.stream().map(KojiBuild::getId).collect(Collectors.joining(", ")); - log.warn( - "Multiple builds (with ids: {}) where found in Brew of the artifact '{}', picking the first one!", - brewBuildIds, - artifact.getPublicUrl()); - return brewBuilds.get(0); - } - } catch (Throwable e) { - log.error("Lookup in Brew failed due to {}", e.getMessage() == null ? e.toString() : e.getMessage(), e); + FinderStatus status = new FinderStatus(); + log.trace("Searching for artifact '{}' in Brew...", artifact.getPublicUrl()); + List brewBuilds = find(artifact.getPublicUrl(), status, status); + if (brewBuilds.size() == 1) { + log.trace( + "Found Brew build with id {} of artifact: '{}'", + brewBuilds.get(0).getId(), + artifact.getPublicUrl()); + return brewBuilds.get(0); + } else if (brewBuilds.size() > 1) { + String brewBuildIds = brewBuilds.stream().map(KojiBuild::getId).collect(Collectors.joining(", ")); + log.warn( + "Multiple builds (with ids: {}) where found in Brew of the artifact '{}', picking the first one!", + brewBuildIds, + artifact.getPublicUrl()); + return brewBuilds.get(0); } return null; } + @Retry(maxRetries = KOJI_SERVICE_MAX_RETRIES, delay = KOJI_SERVICE_DELAY, delayUnit = ChronoUnit.SECONDS) public KojiBuildInfo findBuildByRPM(String nvra) throws KojiClientException { if (nvra == null) { return null; @@ -267,6 +261,7 @@ public KojiBuildInfo findBuildByRPM(String nvra) throws KojiClientException { return buildInfo; } + @Retry(maxRetries = KOJI_SERVICE_MAX_RETRIES, delay = KOJI_SERVICE_DELAY, delayUnit = ChronoUnit.SECONDS) public KojiBuildInfo findBuild(int id) throws KojiClientException { log.debug("Retrieving Brew build with id '{}'...", id); @@ -280,6 +275,7 @@ public KojiBuildInfo findBuild(int id) throws KojiClientException { return build; } + @Retry(maxRetries = KOJI_SERVICE_MAX_RETRIES, delay = KOJI_SERVICE_DELAY, delayUnit = ChronoUnit.SECONDS) public KojiBuildInfo findBuild(String nvr) throws KojiClientException { if (nvr == null) { return null; diff --git a/core/src/main/java/org/jboss/sbomer/core/rest/faulttolerance/Constants.java b/core/src/main/java/org/jboss/sbomer/core/rest/faulttolerance/Constants.java index aa2d56937..43552ff6f 100644 --- a/core/src/main/java/org/jboss/sbomer/core/rest/faulttolerance/Constants.java +++ b/core/src/main/java/org/jboss/sbomer/core/rest/faulttolerance/Constants.java @@ -23,6 +23,7 @@ public class Constants { public static final int ERRATA_CLIENT_MAX_RETRIES = 15; public static final int PYXIS_CLIENT_MAX_RETRIES = 15; public static final int ATLAS_CLIENT_MAX_RETRIES = 15; + public static final int KOJI_SERVICE_MAX_RETRIES = 15; public static final int KOJI_DOWNLOAD_CLIENT_MAX_RETRIES = 15; public static final int SBOMER_CLIENT_MAX_RETRIES = 15; @@ -30,6 +31,7 @@ public class Constants { public static final long ERRATA_CLIENT_DELAY = 1; public static final long PYXIS_CLIENT_DELAY = 1; public static final long ATLAS_CLIENT_DELAY = 1; + public static final long KOJI_SERVICE_DELAY = 1; public static final long KOJI_DOWNLOAD_CLIENT_DELAY = 1; public static final long SBOMER_CLIENT_DELAY = 1;