Skip to content

feat(gax): add RewindableStreamBuffer for single-chunk rewinds and seeks - #14224

Draft
whowes wants to merge 1 commit into
whowes/resumable-upload-statusfrom
whowes/rewindable-stream-buffer
Draft

feat(gax): add RewindableStreamBuffer for single-chunk rewinds and seeks#14224
whowes wants to merge 1 commit into
whowes/resumable-upload-statusfrom
whowes/rewindable-stream-buffer

Conversation

@whowes

@whowes whowes commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Work in progress - not yet ready for review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces RewindableStreamBuffer, a new stream buffer supporting single-chunk rewind and seeking over an InputStream for resumable uploads, along with its corresponding unit tests. The feedback suggests adding a precondition check in readChunk to ensure the requested targetOffset matches the actual streamPosition to prevent potential data corruption. Additionally, it is recommended to remove the unused chunkSize field and constructor parameter from both the class and its tests.

Comment on lines +84 to +87

if (endOfStream) {
return ByteString.EMPTY;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If targetOffset does not match streamPosition when reading a new chunk from the stream, it means we are attempting to read from an incorrect position in the underlying stream (either because we skipped bytes without seeking, or because we are trying to read an invalid offset). Without this check, the buffer would silently read incorrect data from the stream and associate it with the wrong offset, leading to silent data corruption.

Adding a precondition check ensures that the caller's requested offset matches the actual stream position before reading.

    checkArgument(
        targetOffset == streamPosition,
        "targetOffset (%s) must match streamPosition (%s) when reading from the stream",
        targetOffset,
        streamPosition);

    if (endOfStream) {
      return ByteString.EMPTY;
    }

Comment on lines +52 to +64
private final InputStream source;
private final int chunkSize;

private byte @Nullable [] currentChunkData;
private long currentChunkStartOffset = 0L;
private long streamPosition = 0L;
private boolean endOfStream = false;

public RewindableStreamBuffer(InputStream source, int chunkSize) {
this.source = checkNotNull(source);
checkArgument(chunkSize > 0, "chunkSize must be > 0");
this.chunkSize = chunkSize;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The chunkSize field and constructor parameter are completely unused in this class. To simplify the API and avoid dead code, we should remove them.

  private final InputStream source;

  private byte @Nullable [] currentChunkData;
  private long currentChunkStartOffset = 0L;
  private long streamPosition = 0L;
  private boolean endOfStream = false;

  public RewindableStreamBuffer(InputStream source) {
    this.source = checkNotNull(source);
  }

import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;

class RewindableStreamBufferTest {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the unused chunkSize parameter is removed from the RewindableStreamBuffer constructor, please update all constructor calls in this test file to omit the second argument (e.g., new RewindableStreamBuffer(stream)), and remove the testInvalidChunkSize test case.

@whowes
whowes force-pushed the whowes/rewindable-stream-buffer branch from e73249a to 5407505 Compare September 1, 2026 06:29
@whowes
whowes force-pushed the whowes/resumable-upload-status branch 2 times, most recently from 4b3b68b to ddfd13c Compare September 1, 2026 06:39
@whowes
whowes force-pushed the whowes/rewindable-stream-buffer branch from 5407505 to b706b52 Compare September 1, 2026 06:39
@whowes
whowes force-pushed the whowes/rewindable-stream-buffer branch from b706b52 to 3d41927 Compare September 1, 2026 07:03
@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed for 'gapic-generator-java-root'

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant