blob: 70c75c08e7e11994b6d5e5a2b996effbb8769c9a [file] [log] [blame]
// Copyright 2024 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
import static com.google.common.io.BaseEncoding.base16;
import static com.google.devtools.build.lib.skyframe.serialization.SkyValueRetriever.NoCachedData.NO_CACHED_DATA;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skyframe.serialization.DependOnFutureShim.DefaultDependOnFutureShim;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.devtools.build.lib.skyframe.serialization.SkyValueRetriever;
import com.google.devtools.build.lib.skyframe.serialization.SkyValueRetriever.Restart;
import com.google.devtools.build.lib.skyframe.serialization.SkyValueRetriever.RetrievalContext;
import com.google.devtools.build.lib.skyframe.serialization.SkyValueRetriever.RetrievalResult;
import com.google.devtools.build.lib.skyframe.serialization.SkyValueRetriever.SerializableSkyKeyComputeState;
import com.google.devtools.build.lib.skyframe.serialization.analysis.RemoteAnalysisCachingDependenciesProvider;
import com.google.devtools.build.lib.skyframe.serialization.analysis.RemoteAnalysisJsonLogWriter;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyKey;
import java.time.Instant;
import java.util.function.Supplier;
/**
* A wrapper around {@link SkyValueRetriever} to handle Bazel-on-Skyframe specific logic, metrics
* gathering, and error handling.
*/
public final class SkyValueRetrieverUtils {
public static RetrievalResult retrieveRemoteSkyValue(
SkyKey key,
Environment env,
RemoteAnalysisCachingDependenciesProvider analysisCachingDeps,
Supplier<? extends SerializableSkyKeyComputeState> stateSupplier)
throws InterruptedException {
Label label =
switch (key) {
case ActionLookupKey alk -> alk.getLabel();
case ActionLookupData ald -> ald.getLabel();
case Artifact artifact -> artifact.getOwnerLabel();
default -> throw new IllegalStateException("unexpected key: " + key.getCanonicalName());
};
if (label == null) {
// If there's no label, there's no cached data.
return NO_CACHED_DATA;
}
RetrievalResult retrievalResult = null;
Exception exception = null;
RetrievalContext state = env.getState(stateSupplier).getRetrievalContext();
try {
retrievalResult =
SkyValueRetriever.tryRetrieve(
env,
new DefaultDependOnFutureShim(env),
analysisCachingDeps.getObjectCodecs(),
analysisCachingDeps.getFingerprintValueService(),
analysisCachingDeps.getAnalysisCacheClient(),
key,
state,
/* frontierNodeVersion= */ analysisCachingDeps.getSkyValueVersion());
analysisCachingDeps.recordRetrievalResult(retrievalResult, key);
} catch (SerializationException e) {
// Don't crash the build if deserialization failed. Gracefully fallback to local evaluation.
analysisCachingDeps.recordSerializationException(e);
exception = e;
retrievalResult = NO_CACHED_DATA;
} catch (RuntimeException | InterruptedException e) {
exception = e;
throw e;
} finally {
if (retrievalResult == Restart.RESTART) {
state.addRestart();
} else if (analysisCachingDeps.getJsonLogWriter() != null && !state.isLogged()) {
RemoteAnalysisJsonLogWriter logWriter = analysisCachingDeps.getJsonLogWriter();
try (var entry = logWriter.startEntry("retrieve")) {
entry.addField("start", state.getStart());
entry.addField("end", Instant.now());
entry.addField("skyKey", key.toString());
entry.addField("cacheKey", base16().lowerCase().encode(state.getCacheKey().toBytes()));
entry.addField("restarts", state.getRestarts());
if (retrievalResult != null) {
entry.addField("result", retrievalResult.toString());
}
if (exception != null) {
entry.addField("exception", exception.getMessage());
}
}
state.setLogged();
}
}
return retrievalResult;
}
private SkyValueRetrieverUtils() {}
}