Search in sources :

Example 1 with Backplane

use of build.buildfarm.backplane.Backplane in project bazel-buildfarm by bazelbuild.

the class RemoteInputStreamFactory method newInput.

@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
public InputStream newInput(Digest blobDigest, long offset, long deadlineAfter, TimeUnit deadlineAfterUnits, RequestMetadata requestMetadata) throws IOException, InterruptedException {
    Set<String> remoteWorkers;
    Set<String> locationSet;
    try {
        Set<String> workers = backplane.getWorkers();
        if (publicName == null) {
            remoteWorkers = workers;
        } else {
            synchronized (workers) {
                remoteWorkers = Sets.difference(workers, ImmutableSet.of(publicName)).immutableCopy();
            }
        }
        locationSet = Sets.newHashSet(Sets.intersection(backplane.getBlobLocationSet(blobDigest), workers));
    } catch (IOException e) {
        throw Status.fromThrowable(e).asRuntimeException();
    }
    if (publicName != null && locationSet.remove(publicName)) {
        backplane.removeBlobLocation(blobDigest, publicName);
    }
    List<String> workersList = new ArrayList<>(locationSet);
    boolean emptyWorkerList = workersList.isEmpty();
    final ListenableFuture<List<String>> populatedWorkerListFuture;
    if (emptyWorkerList) {
        populatedWorkerListFuture = transform(correctMissingBlob(backplane, remoteWorkers, locationSet, this::workerStub, blobDigest, newDirectExecutorService(), requestMetadata), (foundOnWorkers) -> {
            Iterables.addAll(workersList, foundOnWorkers);
            return workersList;
        }, directExecutor());
    } else {
        populatedWorkerListFuture = immediateFuture(workersList);
    }
    SettableFuture<InputStream> inputStreamFuture = SettableFuture.create();
    addCallback(populatedWorkerListFuture, new WorkersCallback(rand) {

        boolean triedCheck = emptyWorkerList;

        @Override
        public void onQueue(Deque<String> workers) {
            Set<String> locationSet = Sets.newHashSet(workers);
            boolean complete = false;
            while (!complete && !workers.isEmpty()) {
                try {
                    inputStreamFuture.set(fetchBlobFromRemoteWorker(blobDigest, workers, offset, deadlineAfter, deadlineAfterUnits, requestMetadata));
                    complete = true;
                } catch (IOException e) {
                    if (workers.isEmpty()) {
                        if (triedCheck) {
                            onFailure(e);
                            return;
                        }
                        triedCheck = true;
                        workersList.clear();
                        ListenableFuture<List<String>> checkedWorkerListFuture = transform(correctMissingBlob(backplane, remoteWorkers, locationSet, RemoteInputStreamFactory.this::workerStub, blobDigest, newDirectExecutorService(), requestMetadata), (foundOnWorkers) -> {
                            Iterables.addAll(workersList, foundOnWorkers);
                            return workersList;
                        }, directExecutor());
                        addCallback(checkedWorkerListFuture, this, directExecutor());
                        complete = true;
                    }
                } catch (InterruptedException e) {
                    complete = true;
                    onFailure(e);
                }
            }
        }

        @SuppressWarnings("NullableProblems")
        @Override
        public void onFailure(Throwable t) {
            Status status = Status.fromThrowable(t);
            if (status.getCode() == Code.NOT_FOUND) {
                inputStreamFuture.setException(new NoSuchFileException(DigestUtil.toString(blobDigest)));
            } else {
                inputStreamFuture.setException(t);
            }
        }
    }, directExecutor());
    try {
        return inputStreamFuture.get();
    } catch (ExecutionException e) {
        Throwable cause = e.getCause();
        Throwables.throwIfUnchecked(cause);
        Throwables.throwIfInstanceOf(cause, IOException.class);
        Throwables.throwIfInstanceOf(cause, InterruptedException.class);
        throw new UncheckedExecutionException(cause);
    }
}
Also used : Iterables(com.google.common.collect.Iterables) NoSuchFileException(java.nio.file.NoSuchFileException) LoadingCache(com.google.common.cache.LoadingCache) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) MoreExecutors.newDirectExecutorService(com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Random(java.util.Random) Util.correctMissingBlob(build.buildfarm.instance.shard.Util.correctMissingBlob) InputStreamFactory(build.buildfarm.common.InputStreamFactory) SettableFuture(com.google.common.util.concurrent.SettableFuture) Deque(java.util.Deque) DigestUtil(build.buildfarm.common.DigestUtil) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) SHARD_IS_RETRIABLE(build.buildfarm.instance.shard.Util.SHARD_IS_RETRIABLE) Code(io.grpc.Status.Code) Futures.addCallback(com.google.common.util.concurrent.Futures.addCallback) Digest(build.bazel.remote.execution.v2.Digest) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) Status(io.grpc.Status) Nullable(javax.annotation.Nullable) WorkersCallback(build.buildfarm.instance.shard.ShardInstance.WorkersCallback) Backplane(build.buildfarm.backplane.Backplane) Futures.immediateFuture(com.google.common.util.concurrent.Futures.immediateFuture) ImmutableSet(com.google.common.collect.ImmutableSet) Throwables(com.google.common.base.Throwables) Set(java.util.Set) IOException(java.io.IOException) Logger(java.util.logging.Logger) Instance(build.buildfarm.instance.Instance) Sets(com.google.common.collect.Sets) MoreExecutors.directExecutor(com.google.common.util.concurrent.MoreExecutors.directExecutor) StatusRuntimeException(io.grpc.StatusRuntimeException) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Futures.transform(com.google.common.util.concurrent.Futures.transform) SECONDS(java.util.concurrent.TimeUnit.SECONDS) InputStream(java.io.InputStream) Status(io.grpc.Status) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) NoSuchFileException(java.nio.file.NoSuchFileException) IOException(java.io.IOException) WorkersCallback(build.buildfarm.instance.shard.ShardInstance.WorkersCallback) ArrayList(java.util.ArrayList) List(java.util.List) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) ExecutionException(java.util.concurrent.ExecutionException)

Example 2 with Backplane

use of build.buildfarm.backplane.Backplane in project bazel-buildfarm by bazelbuild.

the class UtilTest method correctMissingBlobChecksAllWorkers.

@Test
public void correctMissingBlobChecksAllWorkers() throws Exception {
    String worker1Name = "worker1";
    String worker2Name = "worker2";
    String worker3Name = "worker3";
    Set<String> workerSet = ImmutableSet.of(worker1Name, worker2Name, worker3Name);
    Digest digest = Digest.newBuilder().setHash("digest").setSizeBytes(1).build();
    ImmutableList<Digest> digests = ImmutableList.of(digest);
    Instance foundInstance = mock(Instance.class);
    when(foundInstance.findMissingBlobs(eq(digests), any(RequestMetadata.class))).thenReturn(immediateFuture(ImmutableList.of()));
    Instance missingInstance = mock(Instance.class);
    when(missingInstance.findMissingBlobs(eq(digests), any(RequestMetadata.class))).thenReturn(immediateFuture(ImmutableList.of(digest)));
    Backplane backplane = mock(Backplane.class);
    Function<String, Instance> workerInstanceFactory = worker -> {
        if (worker.equals(worker1Name)) {
            return missingInstance;
        }
        if (worker.equals(worker2Name) || worker.equals(worker3Name)) {
            return foundInstance;
        }
        return null;
    };
    ListenableFuture<Set<String>> correctFuture = correctMissingBlob(backplane, workerSet, /* originalLocationSet=*/
    ImmutableSet.of(), workerInstanceFactory, digest, directExecutor(), RequestMetadata.getDefaultInstance());
    assertThat(correctFuture.get()).isEqualTo(ImmutableSet.of(worker2Name, worker3Name));
    verify(foundInstance, times(2)).findMissingBlobs(eq(digests), any(RequestMetadata.class));
    verify(missingInstance, times(1)).findMissingBlobs(eq(digests), any(RequestMetadata.class));
    verify(backplane, times(1)).adjustBlobLocations(eq(digest), eq(ImmutableSet.of(worker2Name, worker3Name)), eq(ImmutableSet.of()));
}
Also used : ListenableFuture(com.google.common.util.concurrent.ListenableFuture) RunWith(org.junit.runner.RunWith) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Util.correctMissingBlob(build.buildfarm.instance.shard.Util.correctMissingBlob) Function(java.util.function.Function) Mockito.verifyZeroInteractions(org.mockito.Mockito.verifyZeroInteractions) Mockito.doThrow(org.mockito.Mockito.doThrow) Code(io.grpc.Status.Code) ImmutableList(com.google.common.collect.ImmutableList) Digest(build.bazel.remote.execution.v2.Digest) Status(io.grpc.Status) Backplane(build.buildfarm.backplane.Backplane) Futures.immediateFuture(com.google.common.util.concurrent.Futures.immediateFuture) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Mockito.times(org.mockito.Mockito.times) IOException(java.io.IOException) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) JUnit4(org.junit.runners.JUnit4) Truth.assertThat(com.google.common.truth.Truth.assertThat) Instance(build.buildfarm.instance.Instance) MoreExecutors.directExecutor(com.google.common.util.concurrent.MoreExecutors.directExecutor) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) Futures.immediateFailedFuture(com.google.common.util.concurrent.Futures.immediateFailedFuture) Mockito.any(org.mockito.Mockito.any) Mockito.eq(org.mockito.Mockito.eq) Mockito.mock(org.mockito.Mockito.mock) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Digest(build.bazel.remote.execution.v2.Digest) Instance(build.buildfarm.instance.Instance) Backplane(build.buildfarm.backplane.Backplane) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Test(org.junit.Test)

Example 3 with Backplane

use of build.buildfarm.backplane.Backplane in project bazel-buildfarm by bazelbuild.

the class UtilTest method correctMissingBlobIgnoresBackplaneException.

@Test
public void correctMissingBlobIgnoresBackplaneException() throws Exception {
    String workerName = "worker";
    Set<String> workerSet = ImmutableSet.of(workerName);
    Digest digest = Digest.newBuilder().setHash("digest").setSizeBytes(1).build();
    ImmutableList<Digest> digests = ImmutableList.of(digest);
    Instance instance = mock(Instance.class);
    when(instance.findMissingBlobs(eq(digests), any(RequestMetadata.class))).thenReturn(immediateFailedFuture(Status.UNKNOWN.asRuntimeException())).thenReturn(immediateFuture(ImmutableList.of()));
    Backplane backplane = mock(Backplane.class);
    doThrow(new IOException("failed to adjustBlobLocations")).when(backplane).adjustBlobLocations(eq(digest), eq(ImmutableSet.of(workerName)), eq(ImmutableSet.of()));
    Function<String, Instance> workerInstanceFactory = worker -> {
        if (worker.equals(workerName)) {
            return instance;
        }
        return null;
    };
    ListenableFuture<Set<String>> correctFuture = correctMissingBlob(backplane, workerSet, /* originalLocationSet=*/
    ImmutableSet.of(), workerInstanceFactory, digest, directExecutor(), RequestMetadata.getDefaultInstance());
    assertThat(correctFuture.get()).isEqualTo(ImmutableSet.of(workerName));
    verify(instance, times(2)).findMissingBlobs(eq(digests), any(RequestMetadata.class));
    verify(backplane, times(1)).adjustBlobLocations(eq(digest), eq(ImmutableSet.of(workerName)), eq(ImmutableSet.of()));
}
Also used : ListenableFuture(com.google.common.util.concurrent.ListenableFuture) RunWith(org.junit.runner.RunWith) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Util.correctMissingBlob(build.buildfarm.instance.shard.Util.correctMissingBlob) Function(java.util.function.Function) Mockito.verifyZeroInteractions(org.mockito.Mockito.verifyZeroInteractions) Mockito.doThrow(org.mockito.Mockito.doThrow) Code(io.grpc.Status.Code) ImmutableList(com.google.common.collect.ImmutableList) Digest(build.bazel.remote.execution.v2.Digest) Status(io.grpc.Status) Backplane(build.buildfarm.backplane.Backplane) Futures.immediateFuture(com.google.common.util.concurrent.Futures.immediateFuture) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Mockito.times(org.mockito.Mockito.times) IOException(java.io.IOException) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) JUnit4(org.junit.runners.JUnit4) Truth.assertThat(com.google.common.truth.Truth.assertThat) Instance(build.buildfarm.instance.Instance) MoreExecutors.directExecutor(com.google.common.util.concurrent.MoreExecutors.directExecutor) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) Futures.immediateFailedFuture(com.google.common.util.concurrent.Futures.immediateFailedFuture) Mockito.any(org.mockito.Mockito.any) Mockito.eq(org.mockito.Mockito.eq) Mockito.mock(org.mockito.Mockito.mock) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Digest(build.bazel.remote.execution.v2.Digest) Instance(build.buildfarm.instance.Instance) Backplane(build.buildfarm.backplane.Backplane) IOException(java.io.IOException) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Test(org.junit.Test)

Example 4 with Backplane

use of build.buildfarm.backplane.Backplane in project bazel-buildfarm by bazelbuild.

the class UtilTest method correctMissingBlobFailsImmediatelyOnUnretriable.

@Test
public void correctMissingBlobFailsImmediatelyOnUnretriable() throws InterruptedException {
    String workerName = "worker";
    Backplane backplane = mock(Backplane.class);
    Set<String> workerSet = ImmutableSet.of(workerName);
    Digest digest = Digest.newBuilder().setHash("digest-throws-exception-on-find-missing").setSizeBytes(1).build();
    ImmutableList<Digest> digests = ImmutableList.of(digest);
    Instance instance = mock(Instance.class);
    when(instance.findMissingBlobs(eq(digests), any(RequestMetadata.class))).thenReturn(immediateFailedFuture(Status.INVALID_ARGUMENT.asRuntimeException()));
    Function<String, Instance> workerInstanceFactory = worker -> {
        if (worker.equals(workerName)) {
            return instance;
        }
        return null;
    };
    ListenableFuture<Set<String>> correctFuture = correctMissingBlob(backplane, workerSet, /* originalLocationSet=*/
    ImmutableSet.of(), workerInstanceFactory, digest, directExecutor(), RequestMetadata.getDefaultInstance());
    boolean caughtException = false;
    try {
        correctFuture.get();
    } catch (ExecutionException e) {
        caughtException = true;
        Status status = Status.fromThrowable(e.getCause());
        assertThat(status.getCode()).isEqualTo(Code.INVALID_ARGUMENT);
    }
    verify(instance, times(1)).findMissingBlobs(eq(digests), any(RequestMetadata.class));
    assertThat(caughtException).isTrue();
    verifyZeroInteractions(backplane);
}
Also used : ListenableFuture(com.google.common.util.concurrent.ListenableFuture) RunWith(org.junit.runner.RunWith) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Util.correctMissingBlob(build.buildfarm.instance.shard.Util.correctMissingBlob) Function(java.util.function.Function) Mockito.verifyZeroInteractions(org.mockito.Mockito.verifyZeroInteractions) Mockito.doThrow(org.mockito.Mockito.doThrow) Code(io.grpc.Status.Code) ImmutableList(com.google.common.collect.ImmutableList) Digest(build.bazel.remote.execution.v2.Digest) Status(io.grpc.Status) Backplane(build.buildfarm.backplane.Backplane) Futures.immediateFuture(com.google.common.util.concurrent.Futures.immediateFuture) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Mockito.times(org.mockito.Mockito.times) IOException(java.io.IOException) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) JUnit4(org.junit.runners.JUnit4) Truth.assertThat(com.google.common.truth.Truth.assertThat) Instance(build.buildfarm.instance.Instance) MoreExecutors.directExecutor(com.google.common.util.concurrent.MoreExecutors.directExecutor) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) Futures.immediateFailedFuture(com.google.common.util.concurrent.Futures.immediateFailedFuture) Mockito.any(org.mockito.Mockito.any) Mockito.eq(org.mockito.Mockito.eq) Mockito.mock(org.mockito.Mockito.mock) Status(io.grpc.Status) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Digest(build.bazel.remote.execution.v2.Digest) Instance(build.buildfarm.instance.Instance) Backplane(build.buildfarm.backplane.Backplane) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Example 5 with Backplane

use of build.buildfarm.backplane.Backplane in project bazel-buildfarm by bazelbuild.

the class UtilTest method correctMissingBlobIgnoresUnavailableWorkers.

@Test
public void correctMissingBlobIgnoresUnavailableWorkers() throws Exception {
    String workerName = "worker";
    String unavailableWorkerName = "unavailableWorker";
    Backplane backplane = mock(Backplane.class);
    Set<String> workerSet = ImmutableSet.of(workerName, unavailableWorkerName);
    Digest digest = Digest.newBuilder().setHash("digest").setSizeBytes(1).build();
    ImmutableList<Digest> digests = ImmutableList.of(digest);
    Instance instance = mock(Instance.class);
    when(instance.findMissingBlobs(eq(digests), any(RequestMetadata.class))).thenReturn(immediateFuture(ImmutableList.of()));
    Instance unavailableInstance = mock(Instance.class);
    when(unavailableInstance.findMissingBlobs(eq(digests), any(RequestMetadata.class))).thenReturn(immediateFailedFuture(Status.UNAVAILABLE.asRuntimeException()));
    Function<String, Instance> workerInstanceFactory = worker -> {
        if (worker.equals(workerName)) {
            return instance;
        }
        if (worker.equals(unavailableWorkerName)) {
            return unavailableInstance;
        }
        return null;
    };
    ListenableFuture<Set<String>> correctFuture = correctMissingBlob(backplane, workerSet, /* originalLocationSet=*/
    ImmutableSet.of(), workerInstanceFactory, digest, directExecutor(), RequestMetadata.getDefaultInstance());
    assertThat(correctFuture.get()).isEqualTo(ImmutableSet.of(workerName));
    verify(instance, times(1)).findMissingBlobs(eq(digests), any(RequestMetadata.class));
    verify(unavailableInstance, times(1)).findMissingBlobs(eq(digests), any(RequestMetadata.class));
    verify(backplane, times(1)).adjustBlobLocations(eq(digest), eq(ImmutableSet.of(workerName)), eq(ImmutableSet.of()));
}
Also used : ListenableFuture(com.google.common.util.concurrent.ListenableFuture) RunWith(org.junit.runner.RunWith) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Util.correctMissingBlob(build.buildfarm.instance.shard.Util.correctMissingBlob) Function(java.util.function.Function) Mockito.verifyZeroInteractions(org.mockito.Mockito.verifyZeroInteractions) Mockito.doThrow(org.mockito.Mockito.doThrow) Code(io.grpc.Status.Code) ImmutableList(com.google.common.collect.ImmutableList) Digest(build.bazel.remote.execution.v2.Digest) Status(io.grpc.Status) Backplane(build.buildfarm.backplane.Backplane) Futures.immediateFuture(com.google.common.util.concurrent.Futures.immediateFuture) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Mockito.times(org.mockito.Mockito.times) IOException(java.io.IOException) Test(org.junit.Test) Mockito.when(org.mockito.Mockito.when) JUnit4(org.junit.runners.JUnit4) Truth.assertThat(com.google.common.truth.Truth.assertThat) Instance(build.buildfarm.instance.Instance) MoreExecutors.directExecutor(com.google.common.util.concurrent.MoreExecutors.directExecutor) Mockito.verify(org.mockito.Mockito.verify) ExecutionException(java.util.concurrent.ExecutionException) Futures.immediateFailedFuture(com.google.common.util.concurrent.Futures.immediateFailedFuture) Mockito.any(org.mockito.Mockito.any) Mockito.eq(org.mockito.Mockito.eq) Mockito.mock(org.mockito.Mockito.mock) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Digest(build.bazel.remote.execution.v2.Digest) Instance(build.buildfarm.instance.Instance) Backplane(build.buildfarm.backplane.Backplane) RequestMetadata(build.bazel.remote.execution.v2.RequestMetadata) Test(org.junit.Test)

Aggregations

Digest (build.bazel.remote.execution.v2.Digest)7 RequestMetadata (build.bazel.remote.execution.v2.RequestMetadata)7 Backplane (build.buildfarm.backplane.Backplane)7 Instance (build.buildfarm.instance.Instance)7 Util.correctMissingBlob (build.buildfarm.instance.shard.Util.correctMissingBlob)7 Futures.immediateFuture (com.google.common.util.concurrent.Futures.immediateFuture)7 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)7 MoreExecutors.directExecutor (com.google.common.util.concurrent.MoreExecutors.directExecutor)7 Status (io.grpc.Status)7 Code (io.grpc.Status.Code)7 IOException (java.io.IOException)7 Set (java.util.Set)7 ExecutionException (java.util.concurrent.ExecutionException)7 ImmutableList (com.google.common.collect.ImmutableList)6 Futures.immediateFailedFuture (com.google.common.util.concurrent.Futures.immediateFailedFuture)6 ImmutableSet (com.google.common.collect.ImmutableSet)5 Truth.assertThat (com.google.common.truth.Truth.assertThat)4 Function (java.util.function.Function)4 Test (org.junit.Test)4 RunWith (org.junit.runner.RunWith)4