Rewriting an object in Cloud Storage copies or transforms an existing object,
such as moving it across locations, rotating its encryption key, or changing its
storage class. Depending on the object size and the
rewrite parameters, Cloud Storage might complete the
operation in a single call or return intermediate progress with a
rewrite_token. When a call returns a rewrite_token, pass that token to
subsequent requests until the rewrite finishes.
This document shows you how to configure a rewrite request and drive the rewrite
loop using the rewrite_until_done helper or a manual loop in the
Cloud Client Libraries for Rust. If you're new to the client library, see
Using Cloud Storage with Rust first.
Before you begin
Before running the code in this document, complete the following prerequisites:
- Create or select a Google Cloud project with billing enabled.
- Create a dedicated test Cloud Storage bucket in your project.
- Configure Application Default Credentials for your environment.
- Grant your principal an Identity and Access Management (IAM) role with permission to
read, write, and delete objects in the bucket, such as Storage Admin
(
roles/storage.admin).
Dependencies
Add the Cloud Storage client library and supporting crates to your
Cargo.toml file:
cargo add google-cloud-storage google-cloud-gax anyhow bytes
cargo add tokio --features macros,rt-multi-thread
Prepare the client and rewrite request
Both the automatic helper and manual loop start from a configured
StorageControl client and RewriteObject request builder. Inside a scope that
accepts bucket_name in the format
projects/_/buckets/BUCKET_ID, complete the following
steps:
Initialize a
StorageControlclient with a retry policy. We recommend allowing at least 30 seconds per request. This example usesRetryableErrorswith a 5-attempt limit and no per-operation overall time limit:Create the
rewrite_objectrequest builder, mark the request idempotent so that the client can retry transient errors, and set the source and destination bucket and object names:Optional: Limit the maximum number of bytes rewritten per call so that individual requests return progress faster instead of requiring a longer request timeout. This example sets a small 1 MiB limit to force multiple iterations; use a larger value in production:
Optional: Specify destination object metadata, such as changing the storage class to Nearline (
NEARLINE):
Run the rewrite loop automatically
For most use cases, bring the RewriteObjectExt trait into scope and call
rewrite_until_done on the request builder. This helper manages the
rewrite_token across iterations and resolves to the destination Object
metadata after the rewrite completes:
Run the rewrite loop manually
If you need to log intermediate byte counts, checkpoint progress, or resume a rewrite from another process, drive the rewrite loop manually:
Define a helper function that sends a single
RewriteObjectrequest, logs progress, and returns either the completedObjectmetadata whenresp.doneistrueor the nextrewrite_token:Call the helper in a loop, cloning the request builder on each iteration and passing the returned token to
set_rewrite_tokenwhenevermake_one_requestreturnsRewriteProgress::Incomplete:
Complete code
The following example uploads a 3 MiB source object and rewrites it to the Nearline storage class in 1 MiB increments using the manual loop. After the rewrite finishes, the example deletes the test objects and empty test bucket:
The output is similar to the following, showing progress across three iterations and the destination object metadata:
PROGRESS: total_bytes_rewritten=1048576; object_size=3145728
PROGRESS: total_bytes_rewritten=2097152; object_size=3145728
DONE: total_bytes_rewritten=3145728; object_size=3145728
dest_object=Object { name: "rewrite-object-clone", ... }
Clean up
If the sample exits early or you run individual snippets without the cleanup helper, delete any remaining test objects and delete your test bucket when you're finished so that you don't incur ongoing charges to your Google Cloud account.