diff --git a/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java b/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java index 1bb79ac91ef63c..bf640f1bfc2aef 100644 --- a/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java +++ b/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java @@ -41,6 +41,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; @@ -53,6 +54,7 @@ public final class GoogleAuthUtils { * @throws IOException in case the channel can't be constructed. */ public static ManagedChannel newChannel( + @Nullable Executor executor, String target, String proxy, AuthAndTLSOptions options, @@ -71,6 +73,7 @@ public static ManagedChannel newChannel( try { NettyChannelBuilder builder = newNettyChannelBuilder(targetUrl, proxy) + .executor(executor) .negotiationType( isTlsEnabled(target) ? NegotiationType.TLS : NegotiationType.PLAINTEXT); if (options.grpcKeepaliveTime != null) { diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java index 006b6f67601b2f..e76b0ecf5c83a2 100644 --- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java +++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java @@ -105,6 +105,7 @@ static Metadata makeGrpcMetadata(BackendConfig config) { @VisibleForTesting protected ManagedChannel newGrpcChannel(BackendConfig config) throws IOException { return GoogleAuthUtils.newChannel( + /*executor=*/ null, config.besBackend(), config.besProxy(), config.authAndTLSOptions(), diff --git a/src/main/java/com/google/devtools/build/lib/remote/BUILD b/src/main/java/com/google/devtools/build/lib/remote/BUILD index 5971a49757912e..1490cc8cb77558 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/BUILD +++ b/src/main/java/com/google/devtools/build/lib/remote/BUILD @@ -42,6 +42,7 @@ java_library( ":ExecutionStatusException", ":ReferenceCountedChannel", ":Retrier", + "//src/main/java/com/google/devtools/build/lib:build-request-options", "//src/main/java/com/google/devtools/build/lib:runtime", "//src/main/java/com/google/devtools/build/lib/actions", "//src/main/java/com/google/devtools/build/lib/actions:action_input_helper", diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java index f9517dd848c357..88b2cc951d9b8b 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java +++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionContextProvider.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.remote; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; @@ -32,14 +33,16 @@ import com.google.devtools.build.lib.remote.util.DigestUtil; import com.google.devtools.build.lib.runtime.CommandEnvironment; import com.google.devtools.build.lib.vfs.Path; +import java.util.concurrent.Executor; import javax.annotation.Nullable; /** Provides a remote execution context. */ final class RemoteActionContextProvider { + private final Executor executor; private final CommandEnvironment env; - @Nullable private final RemoteCache cache; - @Nullable private final RemoteExecutionClient executor; + @Nullable private final RemoteCache remoteCache; + @Nullable private final RemoteExecutionClient remoteExecutor; @Nullable private final ListeningScheduledExecutorService retryScheduler; private final DigestUtil digestUtil; @Nullable private final Path logDir; @@ -47,15 +50,17 @@ final class RemoteActionContextProvider { private RemoteExecutionService remoteExecutionService; private RemoteActionContextProvider( + Executor executor, CommandEnvironment env, - @Nullable RemoteCache cache, - @Nullable RemoteExecutionClient executor, + @Nullable RemoteCache remoteCache, + @Nullable RemoteExecutionClient remoteExecutor, @Nullable ListeningScheduledExecutorService retryScheduler, DigestUtil digestUtil, @Nullable Path logDir) { - this.env = Preconditions.checkNotNull(env, "env"); - this.cache = cache; this.executor = executor; + this.env = Preconditions.checkNotNull(env, "env"); + this.remoteCache = remoteCache; + this.remoteExecutor = remoteExecutor; this.retryScheduler = retryScheduler; this.digestUtil = digestUtil; this.logDir = logDir; @@ -66,27 +71,41 @@ public static RemoteActionContextProvider createForPlaceholder( ListeningScheduledExecutorService retryScheduler, DigestUtil digestUtil) { return new RemoteActionContextProvider( - env, /*cache=*/ null, /*executor=*/ null, retryScheduler, digestUtil, /*logDir=*/ null); + directExecutor(), + env, + /*remoteCache=*/ null, + /*remoteExecutor=*/ null, + retryScheduler, + digestUtil, + /*logDir=*/ null); } public static RemoteActionContextProvider createForRemoteCaching( + Executor executor, CommandEnvironment env, - RemoteCache cache, + RemoteCache remoteCache, ListeningScheduledExecutorService retryScheduler, DigestUtil digestUtil) { return new RemoteActionContextProvider( - env, cache, /*executor=*/ null, retryScheduler, digestUtil, /*logDir=*/ null); + executor, + env, + remoteCache, + /*remoteExecutor=*/ null, + retryScheduler, + digestUtil, + /*logDir=*/ null); } public static RemoteActionContextProvider createForRemoteExecution( + Executor executor, CommandEnvironment env, - RemoteExecutionCache cache, - RemoteExecutionClient executor, + RemoteExecutionCache remoteCache, + RemoteExecutionClient remoteExecutor, ListeningScheduledExecutorService retryScheduler, DigestUtil digestUtil, Path logDir) { return new RemoteActionContextProvider( - env, cache, executor, retryScheduler, digestUtil, logDir); + executor, env, remoteCache, remoteExecutor, retryScheduler, digestUtil, logDir); } private RemotePathResolver createRemotePathResolver() { @@ -120,6 +139,7 @@ private RemoteExecutionService getRemoteExecutionService() { checkNotNull(env.getOptions().getOptions(ExecutionOptions.class)).verboseFailures; remoteExecutionService = new RemoteExecutionService( + executor, env.getReporter(), verboseFailures, env.getExecRoot(), @@ -128,8 +148,8 @@ private RemoteExecutionService getRemoteExecutionService() { env.getCommandId().toString(), digestUtil, checkNotNull(env.getOptions().getOptions(RemoteOptions.class)), - cache, - executor, + remoteCache, + remoteExecutor, filesToDownload, captureCorruptedOutputsDir); env.getEventBus().register(remoteExecutionService); @@ -179,11 +199,11 @@ public void registerSpawnCache(ModuleActionContextRegistry.Builder registryBuild /** Returns the remote cache. */ RemoteCache getRemoteCache() { - return cache; + return remoteCache; } RemoteExecutionClient getRemoteExecutionClient() { - return executor; + return remoteExecutor; } void setFilesToDownload(ImmutableSet topLevelOutputs) { @@ -194,11 +214,11 @@ public void afterCommand() { if (remoteExecutionService != null) { remoteExecutionService.shutdown(); } else { - if (cache != null) { - cache.release(); + if (remoteCache != null) { + remoteCache.release(); } - if (executor != null) { - executor.close(); + if (remoteExecutor != null) { + remoteExecutor.close(); } } } diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteExecutionService.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteExecutionService.java index 7b549dd8f2ba63..28754866bd2aed 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/RemoteExecutionService.java +++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteExecutionService.java @@ -116,6 +116,7 @@ import com.google.protobuf.Message; import io.grpc.Status.Code; import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Scheduler; import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.core.SingleObserver; import io.reactivex.rxjava3.disposables.Disposable; @@ -132,6 +133,7 @@ import java.util.Objects; import java.util.SortedMap; import java.util.TreeSet; +import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.Nullable; @@ -153,10 +155,13 @@ public class RemoteExecutionService { private final ImmutableSet filesToDownload; @Nullable private final Path captureCorruptedOutputsDir; + private final Scheduler scheduler; + private final AtomicBoolean shutdown = new AtomicBoolean(false); private final AtomicBoolean buildInterrupted = new AtomicBoolean(false); public RemoteExecutionService( + Executor executor, Reporter reporter, boolean verboseFailures, Path execRoot, @@ -185,6 +190,8 @@ public RemoteExecutionService( } this.filesToDownload = filesToDownloadBuilder.build(); this.captureCorruptedOutputsDir = captureCorruptedOutputsDir; + + this.scheduler = Schedulers.from(executor, /*interruptibleWorker=*/ true); } static Command buildCommand( @@ -1065,7 +1072,7 @@ public void uploadOutputs(RemoteAction action, SpawnResult spawnResult) remoteCache -> manifest.uploadAsync(action.getRemoteActionExecutionContext(), remoteCache), RemoteCache::release) - .subscribeOn(Schedulers.io()) + .subscribeOn(scheduler) .subscribe( new SingleObserver() { @Override diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java index 289d92c2ad805e..b98fa872ebeb4f 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java +++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java @@ -14,6 +14,8 @@ package com.google.devtools.build.lib.remote; +import static java.util.concurrent.TimeUnit.SECONDS; + import build.bazel.remote.execution.v2.DigestFunction; import build.bazel.remote.execution.v2.ServerCapabilities; import com.google.auth.Credentials; @@ -27,6 +29,7 @@ import com.google.common.flogger.GoogleLogger; import com.google.common.util.concurrent.ListeningScheduledExecutorService; import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.devtools.build.lib.actions.ActionExecutionMetadata; import com.google.devtools.build.lib.actions.ActionGraph; import com.google.devtools.build.lib.actions.ActionInput; @@ -50,6 +53,7 @@ import com.google.devtools.build.lib.buildeventstream.BuildEventArtifactUploader; import com.google.devtools.build.lib.buildeventstream.LocalFilesArtifactUploader; import com.google.devtools.build.lib.buildtool.BuildRequest; +import com.google.devtools.build.lib.buildtool.BuildRequestOptions; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.Reporter; @@ -102,7 +106,11 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; /** RemoteModule provides distributed cache and remote execution for Bazel. */ public final class RemoteModule extends BlazeModule { @@ -114,6 +122,8 @@ public final class RemoteModule extends BlazeModule { private final ListeningScheduledExecutorService retryScheduler = MoreExecutors.listeningDecorator(Executors.newScheduledThreadPool(1)); + private ExecutorService executorService; + private RemoteActionContextProvider actionContextProvider; private RemoteActionInputFetcher actionInputFetcher; private RemoteOutputsMode remoteOutputsMode; @@ -129,7 +139,11 @@ public ManagedChannel newChannel( List interceptors) throws IOException { return GoogleAuthUtils.newChannel( - target, proxy, options, interceptors.isEmpty() ? null : interceptors); + executorService, + target, + proxy, + options, + interceptors.isEmpty() ? null : interceptors); } }; @@ -224,7 +238,7 @@ private void initHttpAndDiskCache( new RemoteCache(env.getReporter(), cacheClient, remoteOptions, digestUtil); actionContextProvider = RemoteActionContextProvider.createForRemoteCaching( - env, remoteCache, /* retryScheduler= */ null, digestUtil); + executorService, env, remoteCache, /* retryScheduler= */ null, digestUtil); } @Override @@ -293,6 +307,24 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException { env.getOutputBase().getRelative(env.getRuntime().getProductName() + "-remote-logs"); cleanAndCreateRemoteLogsDir(logDir); + BuildRequestOptions buildRequestOptions = + env.getOptions().getOptions(BuildRequestOptions.class); + + int jobs = 0; + if (buildRequestOptions != null) { + jobs = buildRequestOptions.jobs; + } + + ThreadFactory threadFactory = + new ThreadFactoryBuilder().setNameFormat("remote-executor-%d").build(); + if (jobs != 0) { + executorService = + new ThreadPoolExecutor( + /*corePoolSize=*/ 0, jobs, 60L, SECONDS, new LinkedBlockingQueue<>(), threadFactory); + } else { + executorService = Executors.newCachedThreadPool(threadFactory); + } + if ((enableHttpCache || enableDiskCache) && !enableGrpcCache) { initHttpAndDiskCache(env, authAndTlsOptions, remoteOptions, digestUtil); return; @@ -547,7 +579,13 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException { new RemoteExecutionCache(env.getReporter(), cacheClient, remoteOptions, digestUtil); actionContextProvider = RemoteActionContextProvider.createForRemoteExecution( - env, remoteCache, remoteExecutor, retryScheduler, digestUtil, logDir); + executorService, + env, + remoteCache, + remoteExecutor, + retryScheduler, + digestUtil, + logDir); repositoryRemoteExecutorFactoryDelegate.init( new RemoteRepositoryRemoteExecutorFactory( remoteCache, @@ -578,7 +616,7 @@ public void beforeCommand(CommandEnvironment env) throws AbruptExitException { new RemoteCache(env.getReporter(), cacheClient, remoteOptions, digestUtil); actionContextProvider = RemoteActionContextProvider.createForRemoteCaching( - env, remoteCache, retryScheduler, digestUtil); + executorService, env, remoteCache, retryScheduler, digestUtil); } if (enableRemoteDownloader) { @@ -773,6 +811,7 @@ public void afterCommand() throws AbruptExitException { logger.atWarning().withCause(e).log(failureMessage); } + executorService = null; buildEventArtifactUploaderFactoryDelegate.reset(); repositoryRemoteExecutorFactoryDelegate.reset(); remoteDownloaderSupplier.set(null); diff --git a/src/main/java/com/google/devtools/build/lib/remote/disk/DiskAndRemoteCacheClient.java b/src/main/java/com/google/devtools/build/lib/remote/disk/DiskAndRemoteCacheClient.java index 6b94bda35a76eb..9c4881e913b83b 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/disk/DiskAndRemoteCacheClient.java +++ b/src/main/java/com/google/devtools/build/lib/remote/disk/DiskAndRemoteCacheClient.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.remote.disk; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static com.google.devtools.build.lib.remote.util.Utils.shouldAcceptCachedResultFromRemoteCache; import static com.google.devtools.build.lib.remote.util.Utils.shouldUploadLocalResultsToRemoteCache; @@ -22,7 +23,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; import com.google.devtools.build.lib.remote.common.LazyFileOutputStream; import com.google.devtools.build.lib.remote.common.RemoteActionExecutionContext; import com.google.devtools.build.lib.remote.common.RemoteCacheClient; @@ -32,7 +32,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.UUID; -import java.util.concurrent.ExecutionException; /** * A {@link RemoteCacheClient} implementation combining two blob stores. A local disk blob store and @@ -61,7 +60,7 @@ public ListenableFuture uploadActionResult( Futures.transformAsync( future, v -> remoteCache.uploadActionResult(context, actionKey, actionResult), - MoreExecutors.directExecutor()); + directExecutor()); } return future; } @@ -75,33 +74,25 @@ public void close() { @Override public ListenableFuture uploadFile( RemoteActionExecutionContext context, Digest digest, Path file) { - try { - diskCache.uploadFile(context, digest, file).get(); - if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) { - remoteCache.uploadFile(context, digest, file).get(); - } - } catch (ExecutionException e) { - return Futures.immediateFailedFuture(e.getCause()); - } catch (InterruptedException e) { - return Futures.immediateFailedFuture(e); + ListenableFuture future = diskCache.uploadFile(context, digest, file); + if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) { + future = + Futures.transformAsync( + future, v -> remoteCache.uploadFile(context, digest, file), directExecutor()); } - return Futures.immediateFuture(null); + return future; } @Override public ListenableFuture uploadBlob( RemoteActionExecutionContext context, Digest digest, ByteString data) { - try { - diskCache.uploadBlob(context, digest, data).get(); - if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) { - remoteCache.uploadBlob(context, digest, data).get(); - } - } catch (ExecutionException e) { - return Futures.immediateFailedFuture(e.getCause()); - } catch (InterruptedException e) { - return Futures.immediateFailedFuture(e); + ListenableFuture future = diskCache.uploadBlob(context, digest, data); + if (shouldUploadLocalResultsToRemoteCache(options, context.getSpawn())) { + future = + Futures.transformAsync( + future, v -> remoteCache.uploadBlob(context, digest, data), directExecutor()); } - return Futures.immediateFuture(null); + return future; } @Override @@ -127,7 +118,7 @@ public ListenableFuture> findMissingDigests( .addAll(remoteQuery.get()) .addAll(diskQuery.get()) .build(), - MoreExecutors.directExecutor()); + directExecutor()); } else { return diskQuery; } @@ -150,7 +141,7 @@ private static ListenableFuture closeStreamOnError( } return Futures.immediateFailedFuture(rootCause); }, - MoreExecutors.directExecutor()); + directExecutor()); } @Override @@ -178,7 +169,7 @@ public ListenableFuture downloadBlob( } return diskCache.downloadBlob(context, digest, out); }, - MoreExecutors.directExecutor()); + directExecutor()); } else { return Futures.immediateFuture(null); } @@ -202,10 +193,10 @@ public ListenableFuture downloadActionResult( diskCache.uploadActionResult( context, actionKey, cachedActionResult.actionResult()), v -> cachedActionResult, - MoreExecutors.directExecutor()); + directExecutor()); } }, - MoreExecutors.directExecutor()); + directExecutor()); } else { return Futures.immediateFuture(null); } diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java index 1c8d10c443b62c..478752d91f74ba 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteExecutionServiceTest.java @@ -14,6 +14,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static com.google.devtools.build.lib.actions.ExecutionRequirements.REMOTE_EXECUTION_INLINE_OUTPUTS; import static com.google.devtools.build.lib.remote.util.DigestUtil.toBinaryDigest; import static com.google.devtools.build.lib.remote.util.Utils.getFromFuture; @@ -1437,6 +1438,7 @@ private RemoteExecutionService newRemoteExecutionService(RemoteOptions remoteOpt private RemoteExecutionService newRemoteExecutionService( RemoteOptions remoteOptions, Collection topLevelOutputs) { return new RemoteExecutionService( + directExecutor(), reporter, /*verboseFailures=*/ true, execRoot, diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java index 9608a1f82680db..474711092d830b 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.remote; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; @@ -207,6 +208,7 @@ private RemoteSpawnCache remoteSpawnCacheWithOptions(RemoteOptions options) { RemoteExecutionService service = spy( new RemoteExecutionService( + directExecutor(), reporter, /*verboseFailures=*/ true, execRoot, diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java index e73531ce612bc7..68fce99846b68b 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerTest.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.remote; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; @@ -1034,6 +1035,7 @@ private void testParamFilesAreMaterializedForFlag(String flag) throws Exception executionOptions.materializeParamFiles = true; RemoteExecutionService remoteExecutionService = new RemoteExecutionService( + directExecutor(), reporter, /*verboseFailures=*/ true, execRoot, @@ -1570,6 +1572,7 @@ private RemoteSpawnRunner newSpawnRunner( RemoteExecutionService service = spy( new RemoteExecutionService( + directExecutor(), reporter, /*verboseFailures=*/ true, execRoot, diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java index 61b20a8548261a..5f5bfefd188017 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.remote; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static com.google.devtools.build.lib.remote.GrpcCacheClient.getResourceName; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.concurrent.TimeUnit.SECONDS; @@ -301,6 +302,7 @@ public int maxConcurrency() { new RemoteExecutionCache(reporter, cacheProtocol, remoteOptions, DIGEST_UTIL); RemoteExecutionService remoteExecutionService = new RemoteExecutionService( + directExecutor(), reporter, /*verboseFailures=*/ true, execRoot,