Skip to content

Commit daa3dbe

Browse files
Yanniccopybara-github
authored andcommitted
[remote] upload: treat ALREADY_EXISTS as success
If the service returns an `ALREADY_EXISTS` error, then we assume that the proper file is present remotely. Prior art: #12112 Fixes #12111 Closes #17692. PiperOrigin-RevId: 515339566 Change-Id: Iafdd288148e47197cc047d39c9a5e5b6c95acee1
1 parent 3ad3927 commit daa3dbe

2 files changed

Lines changed: 30 additions & 4 deletions

File tree

src/main/java/com/google/devtools/build/lib/remote/ByteStreamUploader.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.google.bytestream.ByteStreamProto.WriteResponse;
3131
import com.google.common.annotations.VisibleForTesting;
3232
import com.google.common.base.Ascii;
33+
import com.google.common.base.Preconditions;
3334
import com.google.common.base.Strings;
3435
import com.google.common.util.concurrent.AsyncCallable;
3536
import com.google.common.util.concurrent.Futures;
@@ -391,7 +392,24 @@ private ListenableFuture<Long> upload(long pos) {
391392
channel -> {
392393
SettableFuture<Long> uploadResult = SettableFuture.create();
393394
bsAsyncStub(channel).write(new Writer(resourceName, chunker, pos, uploadResult));
394-
return uploadResult;
395+
return Futures.catchingAsync(
396+
uploadResult,
397+
Throwable.class,
398+
throwable -> {
399+
Preconditions.checkNotNull(throwable);
400+
401+
Status status = Status.fromThrowable(throwable);
402+
switch (status.getCode()) {
403+
case ALREADY_EXISTS:
404+
// Server indicated the blob already exists, so we translate the error to a
405+
// successful upload.
406+
return Futures.immediateFuture(chunker.getSize());
407+
408+
default:
409+
return Futures.immediateFailedFuture(throwable);
410+
}
411+
},
412+
MoreExecutors.directExecutor());
395413
});
396414
}
397415
}

src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,9 +749,12 @@ public void testUploadCacheMissesWithRetries() throws Exception {
749749
fakeFileCache.createScratchInput(ActionInputHelper.fromPath("bar"), "x");
750750
final Digest bazDigest =
751751
fakeFileCache.createScratchInput(ActionInputHelper.fromPath("baz"), "z");
752+
final Digest foobarDigest =
753+
fakeFileCache.createScratchInput(ActionInputHelper.fromPath("foobar"), "foobar");
752754
final Path fooFile = execRoot.getRelative("a/foo");
753755
final Path barFile = execRoot.getRelative("bar");
754756
final Path bazFile = execRoot.getRelative("baz");
757+
final Path foobarFile = execRoot.getRelative("foobar");
755758
ActionKey actionKey = DIGEST_UTIL.asActionKey(fooDigest); // Could be any key.
756759
barFile.setExecutable(true);
757760
serviceRegistry.addService(
@@ -769,6 +772,7 @@ public void findMissingBlobs(
769772
.addMissingBlobDigests(fooDigest)
770773
.addMissingBlobDigests(barDigest)
771774
.addMissingBlobDigests(bazDigest)
775+
.addMissingBlobDigests(foobarDigest)
772776
.build());
773777
responseObserver.onCompleted();
774778
} else {
@@ -782,6 +786,7 @@ public void findMissingBlobs(
782786
rb.addOutputFilesBuilder().setPath("a/foo").setDigest(fooDigest).setIsExecutable(true);
783787
rb.addOutputFilesBuilder().setPath("bar").setDigest(barDigest).setIsExecutable(true);
784788
rb.addOutputFilesBuilder().setPath("baz").setDigest(bazDigest).setIsExecutable(true);
789+
rb.addOutputFilesBuilder().setPath("foobar").setDigest(foobarDigest).setIsExecutable(true);
785790
ActionResult result = rb.build();
786791
serviceRegistry.addService(
787792
new ActionCacheImplBase() {
@@ -837,6 +842,9 @@ public void onNext(WriteRequest request) {
837842
} else if (resourceName.contains(bazDigest.getHash())) {
838843
assertThat(dataStr).isEqualTo("z");
839844
size = 1;
845+
} else if (resourceName.contains(foobarDigest.getHash())) {
846+
responseObserver.onError(Status.ALREADY_EXISTS.asRuntimeException());
847+
return;
840848
} else {
841849
fail("Unexpected resource name in upload: " + resourceName);
842850
}
@@ -874,9 +882,9 @@ public void onError(Throwable t) {
874882
actionKey,
875883
Action.getDefaultInstance(),
876884
Command.getDefaultInstance(),
877-
ImmutableList.<Path>of(fooFile, barFile, bazFile));
878-
// 4 times for the errors, 3 times for the successful uploads.
879-
Mockito.verify(mockByteStreamImpl, Mockito.times(7))
885+
ImmutableList.<Path>of(fooFile, barFile, bazFile, foobarFile));
886+
// 4 times for the errors, 4 times for the successful uploads.
887+
Mockito.verify(mockByteStreamImpl, Mockito.times(8))
880888
.write(ArgumentMatchers.<StreamObserver<WriteResponse>>any());
881889
}
882890

0 commit comments

Comments
 (0)