Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/storage/examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ repository.workspace = true
keywords.workspace = true
categories.workspace = true

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
bytes.workspace = true
Expand Down
72 changes: 72 additions & 0 deletions src/storage/examples/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,77 @@ pub async fn run_object_examples(buckets: &mut Vec<String>) -> anyhow::Result<()
objects::object_csek_to_cmek::sample(&control, &id, "csek_file.txt", new_csek_key, &kms_key)
.await?;

#[cfg(google_cloud_unstable_storage_bidi)]
{
use google_cloud_test_utils::runtime_config::{region_id, zone_id};
tracing::info!("create rapid bucket for appendable examples");
let rapid_bucket_id = random_bucket_id();
buckets.push(rapid_bucket_id.clone());
let _ = control
.create_bucket()
.set_parent("projects/_")
.set_bucket_id(rapid_bucket_id.clone())
.set_bucket(
Bucket::new()
.set_project(format!("projects/{project_id}"))
.set_location(region_id())
.set_custom_placement_config(
CustomPlacementConfig::new().set_data_locations([zone_id()]),
)
.set_storage_class("RAPID")
.set_hierarchical_namespace(HierarchicalNamespace::new().set_enabled(true))
.set_iam_config(IamConfig::new().set_uniform_bucket_level_access(
UniformBucketLevelAccess::new().set_enabled(true),
)),
)
.send()
.await?;

tracing::info!("running open_appendable_object_write example");
objects::open_appendable_object_write::sample(
&client,
&rapid_bucket_id,
"appendable-write",
)
.await?;

tracing::info!("running open_appendable_object_pause_resume example");
objects::open_appendable_object_pause_resume::sample(
&client,
&rapid_bucket_id,
"appendable-pause-resume",
)
.await?;

let mut writer = client
.open_appendable_object(
format!("projects/_/buckets/{rapid_bucket_id}"),
"appendable-finalize",
)
.send()
.await?;
writer.append(bytes::Bytes::from("hello ")).await?;
let generation = writer.generation();
writer.close().await?;

tracing::info!("running open_appendable_object_finalize example");
objects::open_appendable_object_finalize::sample(
&client,
&rapid_bucket_id,
"appendable-finalize",
generation,
)
.await?;

tracing::info!("running open_appendable_object_read_tail example");
objects::open_appendable_object_read_tail::sample(
&client,
&rapid_bucket_id,
"appendable-write",
)
.await?;
}

tracing::info!("create bucket for object ACL, retention examples");
let id = random_bucket_id();
buckets.push(id.clone());
Expand Down Expand Up @@ -548,6 +619,7 @@ pub async fn run_object_examples(buckets: &mut Vec<String>) -> anyhow::Result<()
objects::remove_file_owner::sample(&control, &id, &service_account).await?;
tracing::info!("running set_object_retention_policy example");
objects::set_object_retention_policy::sample(&control, &id).await?;

Ok(())
}

Expand Down
8 changes: 8 additions & 0 deletions src/storage/examples/src/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ pub mod list_object_contexts;
pub mod make_public;
pub mod move_file;
pub mod object_csek_to_cmek;
#[cfg(google_cloud_unstable_storage_bidi)]
pub mod open_appendable_object_finalize;
#[cfg(google_cloud_unstable_storage_bidi)]
pub mod open_appendable_object_pause_resume;
#[cfg(google_cloud_unstable_storage_bidi)]
pub mod open_appendable_object_read_tail;
#[cfg(google_cloud_unstable_storage_bidi)]
pub mod open_appendable_object_write;
pub mod open_multiple_objects_ranged_read;
pub mod open_object_multiple_ranged_read;
pub mod open_object_read_full_object;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// [START storage_open_appendable_object_finalize]
use google_cloud_storage::client::Storage;

pub async fn sample(
client: &Storage,
bucket: &str,
object: &str,
generation: i64,
) -> Result<(), anyhow::Error> {
let writer = client
.reopen_appendable_object(format!("projects/_/buckets/{bucket}"), object, generation)
.send()
.await?;

let metadata = writer.finalize().await?;

println!("Finalized appendable object {object} in bucket {bucket}: {metadata:?}");
Ok(())
}
// [END storage_open_appendable_object_finalize]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// [START storage_open_appendable_object_pause_resume]
use bytes::Bytes;
use google_cloud_storage::client::Storage;

pub async fn sample(client: &Storage, bucket: &str, object: &str) -> Result<(), anyhow::Error> {
let mut writer = client
.open_appendable_object(format!("projects/_/buckets/{bucket}"), object)
.send()
.await?;

writer.append(Bytes::from("Part 1")).await?;
let generation = writer.generation();
writer.close().await?;

let mut resumed_writer = client
.reopen_appendable_object(format!("projects/_/buckets/{bucket}"), object, generation)
.send()
.await?;

resumed_writer.append(Bytes::from("Part 2")).await?;
let metadata = resumed_writer.finalize().await?;

println!("Appended data across multiple sessions to {object} in bucket {bucket}: {metadata:?}");
Ok(())
}
// [END storage_open_appendable_object_pause_resume]
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// [START storage_open_appendable_object_read_tail]
use bytes::Bytes;
use google_cloud_storage::client::Storage;
use google_cloud_storage::model_ext::ReadRange;
use std::time::Duration;
use tokio::time::sleep;

pub async fn sample(client: &Storage, bucket: &str, object: &str) -> Result<(), anyhow::Error> {
let mut writer = client
.open_appendable_object(format!("projects/_/buckets/{bucket}"), object)
.send()
.await?;

let mut bytes_read: u64 = 0;
for i in 0..2 {
let content = format!("More data for tail example, iteration {i}\n");
writer.append(Bytes::from(content)).await?;
writer.flush().await?;

let (_metadata, mut reader) = client
.open_object(format!("projects/_/buckets/{bucket}"), object)
.send_and_read(ReadRange::offset(bytes_read))
.await?;

while let Some(chunk) = reader.next().await.transpose()? {
print!("{}", String::from_utf8_lossy(&chunk));
bytes_read += chunk.len() as u64;
}

sleep(Duration::from_secs(1)).await;
}

Ok(())
}
// [END storage_open_appendable_object_read_tail]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// [START storage_open_appendable_object_write]
use bytes::Bytes;
use google_cloud_storage::client::Storage;

pub async fn sample(client: &Storage, bucket: &str, object: &str) -> Result<(), anyhow::Error> {
let mut writer = client
.open_appendable_object(format!("projects/_/buckets/{bucket}"), object)
.send()
.await?;

writer.append(Bytes::from("Hello ")).await?;
writer.append(Bytes::from("World!")).await?;
let metadata = writer.finalize().await?;

println!("Appended data to {object} in bucket {bucket}: {metadata:?}");
Ok(())
}
// [END storage_open_appendable_object_write]
Loading