Skip to content

Commit

Permalink
feat: add option to exit early if analysis cache is discarded
Browse files Browse the repository at this point in the history
  • Loading branch information
mattem committed Nov 19, 2022
1 parent 0c4de91 commit f59a234
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ public class AnalysisOptions extends OptionsBase {
)
public boolean discardAnalysisCache;

@Option(
name = "fail_on_analysis_cache_discard",
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.EAGERNESS_TO_EXIT},
help = "If discarding the analysis cache due to a change in the build system, setting this option will cause bazel" +
" to exit, rather than continuing with the build. This option has no affect when 'discard_analysis_cache'" +
" is also set."
)
public boolean failOnAnalysisCacheDiscard;

@Option(
name = "max_config_changes_to_show",
defaultValue = "3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,10 @@
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns.Code;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator;
import com.google.devtools.build.lib.skyframe.*;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.TopLevelAspectsKey;
import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.BuildResultListener;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.CoverageReportValue;
import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException;
import com.google.devtools.build.lib.skyframe.SkyframeAnalysisAndExecutionResult;
import com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult;
import com.google.devtools.build.lib.skyframe.SkyframeBuildView;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.RegexFilter;
Expand Down Expand Up @@ -222,7 +213,7 @@ public AnalysisResult update(
@Nullable ExecutionSetup executionSetupCallback,
@Nullable BuildConfigurationsCreated buildConfigurationsCreatedCallback)
throws ViewCreationFailedException, InvalidConfigurationException, InterruptedException,
BuildFailedException, TestExecException, AbruptExitException {
BuildFailedException, TestExecException, AbruptExitException, AnalysisCacheDiscardedException {
logger.atInfo().log("Starting analysis");
pollInterruptedStatus();

Expand Down Expand Up @@ -261,7 +252,7 @@ public AnalysisResult update(
}

skyframeBuildView.setConfigurations(
eventHandler, configurations, viewOptions.maxConfigChangesToShow);
eventHandler, configurations, viewOptions.maxConfigChangesToShow, viewOptions.failOnAnalysisCacheDiscard);

eventBus.post(
new MakeEnvironmentEvent(configurations.getTargetConfiguration().getMakeEnvironment()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,8 @@
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.BuildInfoCollectionFunction;
import com.google.devtools.build.lib.skyframe.BuildResultListener;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.skyframe.*;
import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetAnalyzedEvent;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.DetailedExitCode;
Expand Down Expand Up @@ -81,7 +78,8 @@ static AnalysisAndExecutionResult execute(
BuildConfigurationsCreated buildConfigurationCreatedCallback)
throws BuildFailedException, InterruptedException, ViewCreationFailedException,
TargetParsingException, LoadingFailedException, AbruptExitException,
InvalidConfigurationException, TestExecException, RepositoryMappingResolutionException {
InvalidConfigurationException, TestExecException, RepositoryMappingResolutionException,
AnalysisCacheDiscardedException {

// Compute the heuristic instrumentation filter if needed.
if (request.needsInstrumentationFilter()) {
Expand Down Expand Up @@ -203,7 +201,7 @@ private static AnalysisAndExecutionResult runAnalysisAndExecutionPhase(
BuildConfigurationsCreated buildConfigurationCreatedCallback)
throws InterruptedException, InvalidConfigurationException, ViewCreationFailedException,
BuildFailedException, TestExecException, RepositoryMappingResolutionException,
AbruptExitException {
AbruptExitException, AnalysisCacheDiscardedException {
env.getReporter().handle(Event.progress("Loading complete. Analyzing..."));

ImmutableSet<Label> explicitTargetPatterns =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,9 @@
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.*;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.BuildInfoCollectionFunction;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.AspectAnalyzedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TestAnalyzedEvent;
import com.google.devtools.build.lib.skyframe.TopLevelStatusEvents.TopLevelTargetAnalyzedEvent;
Expand Down Expand Up @@ -87,7 +84,7 @@ public static AnalysisResult execute(
TargetValidator validator)
throws BuildFailedException, InterruptedException, ViewCreationFailedException,
TargetParsingException, LoadingFailedException, AbruptExitException,
InvalidConfigurationException, RepositoryMappingResolutionException {
InvalidConfigurationException, RepositoryMappingResolutionException, AnalysisCacheDiscardedException {

// Target pattern evaluation.
TargetPatternPhaseValue loadingResult;
Expand Down Expand Up @@ -219,7 +216,7 @@ private static AnalysisResult runAnalysisPhase(
TargetPatternPhaseValue loadingResult,
BuildOptions targetOptions)
throws InterruptedException, InvalidConfigurationException,
RepositoryMappingResolutionException, ViewCreationFailedException {
RepositoryMappingResolutionException, ViewCreationFailedException, AnalysisCacheDiscardedException {
Stopwatch timer = Stopwatch.createStarted();
env.getReporter().handle(Event.progress("Loading complete. Analyzing..."));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.server.FailureDetails.ActionQuery;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.AnalysisCacheDiscardedException;
import com.google.devtools.build.lib.skyframe.RepositoryMappingValue.RepositoryMappingResolutionException;
import com.google.devtools.build.lib.skyframe.SequencedSkyframeExecutor;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
Expand Down Expand Up @@ -149,7 +150,7 @@ public void buildTargets(BuildRequest request, BuildResult result, TargetValidat
throws BuildFailedException, InterruptedException, ViewCreationFailedException,
TargetParsingException, LoadingFailedException, AbruptExitException,
InvalidConfigurationException, TestExecException, ExitException,
PostExecutionActionGraphDumpException, RepositoryMappingResolutionException {
PostExecutionActionGraphDumpException, RepositoryMappingResolutionException, AnalysisCacheDiscardedException {
try (SilentCloseable c = Profiler.instance().profile("validateOptions")) {
validateOptions(request);
}
Expand Down Expand Up @@ -307,7 +308,7 @@ private void buildTargetsWithMergedAnalysisExecution(
BuildOptions buildOptions)
throws InterruptedException, TargetParsingException, LoadingFailedException,
AbruptExitException, ViewCreationFailedException, BuildFailedException, TestExecException,
InvalidConfigurationException, RepositoryMappingResolutionException {
InvalidConfigurationException, RepositoryMappingResolutionException, AnalysisCacheDiscardedException {

// Target pattern evaluation.
TargetPatternPhaseValue loadingResult;
Expand Down Expand Up @@ -546,7 +547,7 @@ public BuildResult processRequest(
} else {
result.setCatastrophe();
}
} catch (TargetParsingException | LoadingFailedException e) {
} catch (TargetParsingException | LoadingFailedException | AnalysisCacheDiscardedException e) {
detailedExitCode = e.getDetailedExitCode();
reportExceptionError(e);
} catch (RepositoryMappingResolutionException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.google.devtools.build.lib.skyframe;

import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.util.DetailedExitCode;

/**
* An exception thrown when the analysis cache is discarded, and the `fail_on_analysis_cache_discard` option is
* set.
*/
public class AnalysisCacheDiscardedException extends Exception implements DetailedException {
static final String DISCARD_FLAG = "--fail_on_analysis_cache_discard";

public AnalysisCacheDiscardedException(String diff) {
super(String.format("%s, analysis cache would have been discarded and %s is set.", diff, DISCARD_FLAG));
}

@Override
public DetailedExitCode getDetailedExitCode() {
return DetailedExitCode.of(
FailureDetails.FailureDetail
.newBuilder()
.setMessage(this.getMessage())
.setAnalysis(
FailureDetails.Analysis
.newBuilder()
.setCode(
FailureDetails.Analysis.Code.ANALYSIS_CACHE_DISCARDED
).build()
)
.build()
);
}
}
1 change: 1 addition & 0 deletions src/main/java/com/google/devtools/build/lib/skyframe/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ java_library(
"ActionExecutionFunction.java",
"ActionLookupConflictFindingFunction.java",
"ActionOutputDirectoryHelper.java",
"AnalysisCacheDiscardedException.java",
"AspectCompletor.java",
"AspectFunction.java",
"BazelSkyframeExecutorConstants.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ private ImmutableSet<OptionDefinition> getNativeCacheInvalidatingDifferences(
public void setConfigurations(
EventHandler eventHandler,
BuildConfigurationCollection configurations,
int maxDifferencesToShow) {
int maxDifferencesToShow,
boolean failOnAnalysisCacheDiscard) throws AnalysisCacheDiscardedException {
if (skyframeAnalysisWasDiscarded) {
eventHandler.handle(
Event.info(
Expand All @@ -283,6 +284,10 @@ public void setConfigurations(
} else {
String diff = describeConfigurationDifference(configurations, maxDifferencesToShow);
if (diff != null) {
if (failOnAnalysisCacheDiscard) {
throw new AnalysisCacheDiscardedException(diff);
}

eventHandler.handle(Event.info(diff + ", discarding analysis cache."));
// Note that clearing the analysis cache is currently required for correctness. It is also
// helpful to save memory.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public final class ExitCode {
ExitCode.create(45, "PERSISTENT_BUILD_EVENT_SERVICE_UPLOAD_ERROR");
public static final ExitCode EXTERNAL_DEPS_ERROR = ExitCode.create(48, "EXTERNAL_DEPS_ERROR");

public static final ExitCode ANALYSIS_CACHE_DISCARD_FAILURE =
ExitCode.create(49, "ANALYSIS_CACHE_DISCARD_FAILURE");

/**
* Creates and returns an ExitCode. Requires a unique exit code number.
*
Expand Down
1 change: 1 addition & 0 deletions src/main/protobuf/failure_details.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,7 @@ message Analysis {
CONFIGURED_VALUE_CREATION_FAILED = 18 [(metadata) = { exit_code: 1 }];
INCOMPATIBLE_TARGET_REQUESTED = 19 [(metadata) = { exit_code: 1 }];
ANALYSIS_FAILURE_PROPAGATION_FAILED = 20 [(metadata) = { exit_code: 1 }];
ANALYSIS_CACHE_DISCARDED = 21 [(metadata) = { exit_code: 49 }];
}

Code code = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.skyframe.AnalysisCacheDiscardedException;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
Expand Down Expand Up @@ -201,7 +202,7 @@ public AnalysisResult update(
ExtendedEventHandler eventHandler,
EventBus eventBus)
throws ViewCreationFailedException, InterruptedException, InvalidConfigurationException,
BuildFailedException, TestExecException, AbruptExitException {
BuildFailedException, TestExecException, AbruptExitException, AnalysisCacheDiscardedException {
populateActionLookupKeyMapAndGetDiff();
return buildView.update(
loadingResult,
Expand Down Expand Up @@ -229,8 +230,12 @@ public AnalysisResult update(
/** Sets the configurations. Not thread-safe. */
public void setConfigurationsForTesting(
EventHandler eventHandler, BuildConfigurationCollection configurations) {
skyframeBuildView.setConfigurations(
eventHandler, configurations, /* maxDifferencesToShow */ -1);
try {
skyframeBuildView.setConfigurations(
eventHandler, configurations, /* maxDifferencesToShow */ -1, /* failOnAnalysisCacheDiscard */ false);
} catch (AnalysisCacheDiscardedException e) {
// Will never throw, as failOnAnalysisCacheDiscard is explicitly set false in the call above.
}
}

public ArtifactFactory getArtifactFactory() {
Expand Down

0 comments on commit f59a234

Please sign in to comment.