Skip to content

impl(storage): add appendable upload builder and writer#5697

Open
joshuatants wants to merge 2 commits into
googleapis:mainfrom
joshuatants:appendable_uploads_skeleton
Open

impl(storage): add appendable upload builder and writer#5697
joshuatants wants to merge 2 commits into
googleapis:mainfrom
joshuatants:appendable_uploads_skeleton

Conversation

@joshuatants
Copy link
Copy Markdown
Contributor

No description provided.

@product-auto-label product-auto-label Bot added the api: storage Issues related to the Cloud Storage API. label May 20, 2026
@joshuatants joshuatants requested a review from a team May 20, 2026 07:10
Copy link
Copy Markdown

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

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 the initial framework for appendable object uploads, adding the OpenAppendableObject builder and AppendableObjectWriter under the google_cloud_unstable_storage_bidi feature flag. Review feedback highlighted that the builder lacks configuration methods for request parameters, which is inconsistent with other SDK builders. Furthermore, the use of unimplemented!() in the library code was identified as a violation of the style guide's prohibition on panics.

Comment thread src/storage/src/storage/append_object/builder.rs
Comment on lines +33 to +75
unimplemented!()
}

/// Flushes any pending data to the server and awaits durable persistence on
/// the server.
pub async fn flush(&mut self) -> Result<()> {
unimplemented!()
}

/// Finalizes the upload, sending any pending data. Returns the final [Object][crate::model::Object].
pub async fn finalize(self) -> Result<Object> {
unimplemented!()
}

/// Relinquishes the writer without finalizing, draining any pending data to the server.
/// Returns the final persisted size of the object.
pub async fn close(self) -> Result<i64> {
unimplemented!()
}

/// Returns the latest durable offset confirmed by the server.
pub fn persisted_size(&self) -> i64 {
unimplemented!()
}

/// Returns the server-issued write handle, if available.
pub fn write_handle(&self) -> Option<BidiWriteHandle> {
unimplemented!()
}

/// Returns the generation of the object being appended to.
pub fn generation(&self) -> i64 {
unimplemented!()
}

/// Returns the server-issued routing token, if available.
pub fn routing_token(&self) -> Option<String> {
unimplemented!()
}

/// Returns the latest known object metadata.
pub fn object(&self) -> Option<Object> {
unimplemented!()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

While features can be partially implemented if documented, please avoid using unimplemented!() in library code as it causes panics. Even for unstable features, it is preferred to return a Result with an error or a default value to ensure the application remains stable during development.

References
  1. No panic! macro calls in library code. (link)
  2. A feature does not have to be fully implemented in a single pull request if the remaining work is documented in the PR description or as a TODO comment in the code.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 0% with 51 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.80%. Comparing base (917ed5e) to head (4ae04db).

Files with missing lines Patch % Lines
src/storage/src/storage/append_object/builder.rs 0.00% 21 Missing ⚠️
src/storage/src/storage/append_object/writer.rs 0.00% 14 Missing ⚠️
src/storage/src/storage/stub.rs 0.00% 9 Missing ⚠️
src/storage/src/storage/client.rs 0.00% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5697      +/-   ##
==========================================
- Coverage   97.89%   97.80%   -0.09%     
==========================================
  Files         226      228       +2     
  Lines       55536    55587      +51     
==========================================
+ Hits        54366    54368       +2     
- Misses       1170     1219      +49     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread src/storage/src/storage/append_object/builder.rs Outdated
Comment thread src/storage/src/storage/client.rs Outdated
@joshuatants joshuatants force-pushed the appendable_uploads_skeleton branch 3 times, most recently from 444768e to d000a0e Compare May 20, 2026 08:37
@joshuatants joshuatants marked this pull request as ready for review May 20, 2026 08:44
@joshuatants joshuatants requested a review from a team as a code owner May 20, 2026 08:44
@vsharonlynn
Copy link
Copy Markdown
Contributor

LGTM.

Comment thread src/storage/src/storage/append_object/builder.rs Outdated
Comment thread src/storage/src/storage/append_object/writer.rs Outdated
Comment thread src/storage/src/storage/client.rs Outdated
Comment thread src/storage/src/storage/append_object/writer.rs Outdated
Comment thread src/storage/src/storage/append_object/writer.rs Outdated
Comment thread src/storage/src/storage/append_object/writer.rs Outdated
Comment on lines +212 to +216
/// writer.append(Bytes::from_static(b"hello ")).await?;
/// writer.append(Bytes::from_static(b"world")).await?;
/// writer.flush().await?;
///
/// let object = writer.finalize().await?;
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.

As you know, this inverts the control from the existing writes (and yes, Rust is inverted from the other SDKs).

You could consider:

client.append_to_object("bucket", "object", stream).send().await?

where stream is an asynchronous stream of

enum {
// Add some data
Data(Bytes),
// Relinquish maybe with some extra bytes.
Close(Option<Data>),
// Ditto but finalize
Finalize(Option<Data>),
}

Dunno, may be overly complicated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the pointer. We'll have a think about it. For now, can we get this merged so that we can continue working on the internal plumbing? We should be able to modify this later as long as it's done before we release the API.

@joshuatants joshuatants force-pushed the appendable_uploads_skeleton branch from 8e1d1af to 4ae04db Compare May 22, 2026 01:41
@joshuatants joshuatants changed the title feat(storage): add appendable upload builder and writer impl(storage): add appendable upload builder and writer May 22, 2026
use crate::model::Object;
use bytes::Bytes;

/// A handle to an in-progress appendable object upload.
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.

Maybe you want to add a TODO(#5716) at the top of the file?

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

Labels

api: storage Issues related to the Cloud Storage API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants