diff --git a/src/main/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloader.java b/src/main/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloader.java index d94030930fb9b6..e3adb6f4a620ae 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloader.java +++ b/src/main/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloader.java @@ -82,6 +82,12 @@ public class GrpcRemoteDownloader implements AutoCloseable, Downloader { private static final String QUALIFIER_CHECKSUM_SRI = "checksum.sri"; private static final String QUALIFIER_CANONICAL_ID = "bazel.canonical_id"; + // When this environment variable is set to "1" in the client environment, + // the download order is reversed: the local (HTTP) downloader is tried first, + // and the remote asset API is only used as a fallback. + @VisibleForTesting + static final String REVERSE_REMOTE_API_ATTEMPT_ORDER_ENV = "REVERSE_REMOTE_API_ATTEMPT_ORDER"; + // The `:` character is not permitted in an HTTP header name. So, we use it to // delimit the qualifier prefix which denotes an HTTP header qualifer from the // header name itself. @@ -131,6 +137,32 @@ public void download( Map clientEnv, Optional type) throws IOException, InterruptedException { + boolean localFirst = + fallbackDownloader != null + && "1".equals(clientEnv.get(REVERSE_REMOTE_API_ATTEMPT_ORDER_ENV)); + + if (localFirst) { + try { + fallbackDownloader.download( + urls, + headers, + credentials, + checksum, + canonicalId, + destination, + eventHandler, + clientEnv, + type); + return; + } catch (IOException e) { + eventHandler.handle( + Event.warn( + "Local download failed: " + + e.getMessage() + + ", trying remote downloader")); + } + } + RequestMetadata metadata = TracingMetadataUtils.buildMetadata(buildRequestId, commandId, "remote_downloader", null); RemoteActionExecutionContext remoteActionExecutionContext = @@ -159,11 +191,11 @@ public void download( }); } catch (StatusRuntimeException | IOException e) { - if (fallbackDownloader == null) { + if (localFirst || fallbackDownloader == null) { if (e instanceof StatusRuntimeException) { throw new IOException(e); } - throw e; + throw (IOException) e; } Optional url = urls.stream() @@ -181,7 +213,7 @@ public void download( eventHandler.handle( Event.warn("Remote Cache: " + Utils.grpcAwareErrorMessage(e, verboseFailures))); } - + fallbackDownloader.download( urls, headers,