Skip to content

Commit f195f55

Browse files
authored
chore: ensure generation is included when a grpc ReadObject is retried (#2741)
If a read is opened without a generation, we want to ensure we restart for the same generation. We have this behavior for json This is mainly to avoid a race condition of reading an object (gen=1), that object being replaced (gen=2) then retry attempts to read it again we need to read gen=1 otherwise we will return corrupted data.
1 parent 3bce87a commit f195f55

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/GapicUnbufferedReadableByteChannel.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,15 @@ private void ensureStreamOpen() {
264264
alg,
265265
() -> {
266266
ReadObjectObserver tmp = new ReadObjectObserver();
267-
ReadObjectRequest request = req;
267+
ReadObjectRequest.Builder builder = req.toBuilder();
268268
long currentFetchOffset = fetchOffset.get();
269-
if (request.getReadOffset() != currentFetchOffset) {
270-
request = req.toBuilder().setReadOffset(currentFetchOffset).build();
269+
if (req.getReadOffset() != currentFetchOffset) {
270+
builder.setReadOffset(currentFetchOffset);
271271
}
272-
read.call(request, tmp);
272+
if (metadata != null && req.getGeneration() == 0) {
273+
builder.setGeneration(metadata.getGeneration());
274+
}
275+
read.call(builder.build(), tmp);
273276
ApiExceptions.callAndTranslateApiException(tmp.open);
274277
return tmp;
275278
},

google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedReadableByteChannelTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ public final class ITGapicUnbufferedReadableByteChannelTest {
6666

6767
private final ReadObjectRequest req1 =
6868
ReadObjectRequest.newBuilder().setObject(objectName).setReadOffset(0).build();
69-
private final ReadObjectRequest req2 = req1.toBuilder().setReadOffset(20).build();
69+
private final ReadObjectRequest req2 =
70+
req1.toBuilder().setGeneration(3L).setReadOffset(20).build();
7071
private final ReadObjectResponse resp1 =
7172
ReadObjectResponse.newBuilder()
7273
.setMetadata(expectedResult)

0 commit comments

Comments
 (0)