Skip to content
Merged
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
4 changes: 2 additions & 2 deletions guide/samples/tests/storage/rewrite_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use gcs::Result;
use gcs::builder::storage_control::RewriteObject;
use gcs::client::StorageControl;
use gcs::model::Object;
use gcs::retry_policy::RecommendedPolicy;
use gcs::retry_policy::RetryableErrors;
use google_cloud_gax::retry_policy::RetryPolicyExt as _;
use google_cloud_storage as gcs;

Expand All @@ -26,7 +26,7 @@ pub async fn rewrite_object(bucket_name: &str) -> anyhow::Result<()> {

// ANCHOR: client
let control = StorageControl::builder()
.with_retry_policy(RecommendedPolicy.with_attempt_limit(5))
.with_retry_policy(RetryableErrors.with_attempt_limit(5))
.build()
.await?;
// ANCHOR_END: client
Expand Down
39 changes: 20 additions & 19 deletions src/storage/src/retry_policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
//! - [504 - Gateway Timeout][504]
//!
//! In addition, resumable uploads return [308 - Resume Incomplete][308]. This
//! is not handled by the [recommended][RecommendedPolicy] retry policy.
//! is not handled by the [RetryableErrors] retry policy.
//!
//! [recommends]: https://cloud.google.com/storage/docs/retry-strategy
//! [308]: https://cloud.google.com/storage/docs/json_api/v1/status-codes#308_Resume_Incomplete
Expand All @@ -48,35 +48,33 @@ use std::time::Duration;
///
/// The client will retry all the errors shown as retryable in the service
/// documentation, and stop retrying after 10 seconds.
pub(crate) fn default() -> impl RetryPolicy {
RecommendedPolicy.with_time_limit(Duration::from_secs(10))
pub(crate) fn storage_default() -> impl RetryPolicy {
RetryableErrors.with_time_limit(Duration::from_secs(10))
}

/// The default retry policy for Google Cloud Storage requests.
/// Follows the [retry strategy] recommended by the Cloud Storage service guides.
///
/// This policy must be decorated to limit the number of retry attempts or the
/// duration of the retry loop.
///
/// The policy follows the [retry strategy] recommended by Google Cloud Storage.
/// This policy must be decorated to limit the number of retry attempts and/or
/// the duration of the retry loop.
///
/// # Example
/// ```
/// # use google_cloud_storage::retry_policy::RecommendedPolicy;
/// # use google_cloud_storage::retry_policy::RetryableErrors;
/// use gax::retry_policy::RetryPolicyExt;
/// use google_cloud_storage::client::Storage;
/// use std::time::Duration;
/// let builder = Storage::builder().with_retry_policy(
/// RecommendedPolicy
/// RetryableErrors
/// .with_time_limit(Duration::from_secs(60))
/// .with_attempt_limit(10),
/// );
/// ```
///
/// [retry strategy]: https://cloud.google.com/storage/docs/retry-strategy
#[derive(Clone, Debug)]
pub struct RecommendedPolicy;
pub struct RetryableErrors;

impl RetryPolicy for RecommendedPolicy {
impl RetryPolicy for RetryableErrors {
fn on_error(
&self,
_loop_start: std::time::Instant,
Expand Down Expand Up @@ -112,6 +110,9 @@ impl RetryPolicy for RecommendedPolicy {
}
}

/// Decorate the retry policy to continue on 308 errors.
///
/// Used internally to handle the resumable upload loop.
#[derive(Clone, Debug)]
pub(crate) struct ContinueOn308<T> {
inner: T,
Expand Down Expand Up @@ -153,8 +154,8 @@ mod tests {
#[test_case(502)]
#[test_case(503)]
#[test_case(504)]
fn retryable(code: u16) {
let p = RecommendedPolicy;
fn retryable_http(code: u16) {
let p = RetryableErrors;
let now = std::time::Instant::now();
assert!(p.on_error(now, 0, true, http_error(code)).is_continue());
assert!(p.on_error(now, 0, false, http_error(code)).is_permanent());
Expand All @@ -165,8 +166,8 @@ mod tests {

#[test_case(401)]
#[test_case(403)]
fn not_recommended(code: u16) {
let p = RecommendedPolicy;
fn not_recommended_http(code: u16) {
let p = RetryableErrors;
let now = std::time::Instant::now();
assert!(p.on_error(now, 0, true, http_error(code)).is_permanent());
assert!(p.on_error(now, 0, false, http_error(code)).is_permanent());
Expand All @@ -179,7 +180,7 @@ mod tests {
#[test_case(Code::Internal)]
#[test_case(Code::ResourceExhausted)]
fn retryable_grpc(code: Code) {
let p = RecommendedPolicy;
let p = RetryableErrors;
let now = std::time::Instant::now();
assert!(p.on_error(now, 0, true, grpc_error(code)).is_continue());
assert!(p.on_error(now, 0, false, grpc_error(code)).is_permanent());
Expand All @@ -191,7 +192,7 @@ mod tests {
#[test_case(Code::Unauthenticated)]
#[test_case(Code::PermissionDenied)]
fn not_recommended_grpc(code: Code) {
let p = RecommendedPolicy;
let p = RetryableErrors;
let now = std::time::Instant::now();
assert!(p.on_error(now, 0, true, grpc_error(code)).is_permanent());
assert!(p.on_error(now, 0, false, grpc_error(code)).is_permanent());
Expand All @@ -202,7 +203,7 @@ mod tests {

#[test]
fn continue_on_308() {
let inner: Arc<dyn RetryPolicy + 'static> = Arc::new(RecommendedPolicy);
let inner: Arc<dyn RetryPolicy + 'static> = Arc::new(RetryableErrors);
let p = ContinueOn308::new(inner);
let now = std::time::Instant::now();
assert!(p.on_error(now, 0, true, http_error(308)).is_continue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ async fn start_too_many_transients() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", "")
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_buffered()
.await
Expand Down Expand Up @@ -529,7 +529,7 @@ async fn put_too_many_transients() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", "")
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_buffered()
.await
Expand Down Expand Up @@ -609,7 +609,7 @@ async fn put_partial_and_recover() -> Result {
.await?;
let upload = client
.write_object("projects/_/buckets/test-bucket", "test-object", payload)
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.with_resumable_upload_buffer_size(TARGET);
let response = upload.send_buffered().await;
Expand Down Expand Up @@ -663,7 +663,7 @@ async fn put_error_and_finalized() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", payload)
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_buffered()
.await?;
Expand Down
2 changes: 1 addition & 1 deletion src/storage/src/storage/perform_upload/unbuffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ mod tests {
"hello",
)
.set_if_generation_match(0)
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.send_unbuffered()
.await
.expect_err("expected permanent error");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ async fn resumable_start_too_many_transients() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", "")
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_unbuffered()
.await
Expand Down Expand Up @@ -539,7 +539,7 @@ async fn resumable_query_too_many_transients() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", "")
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_unbuffered()
.await
Expand Down Expand Up @@ -638,7 +638,7 @@ async fn resumable_put_too_many_transients() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", "")
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_unbuffered()
.await
Expand Down Expand Up @@ -707,7 +707,7 @@ async fn resumable_put_partial_and_recover_unknown_size() -> Result {
"test-object",
UnknownSize::new(BytesSource::new(payload)),
)
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_unbuffered()
.await?;
Expand Down Expand Up @@ -776,7 +776,7 @@ async fn resumable_put_partial_and_recover_known_size() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", payload)
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_unbuffered()
.await?;
Expand Down Expand Up @@ -828,7 +828,7 @@ async fn resumable_put_error_and_finalized() -> Result {
.await?;
let response = client
.write_object("projects/_/buckets/test-bucket", "test-object", payload)
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.set_if_generation_match(0_i64)
.send_unbuffered()
.await?;
Expand Down
9 changes: 5 additions & 4 deletions src/storage/src/storage/read_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,14 +311,15 @@ where
/// ```
/// # use google_cloud_storage::client::Storage;
/// # async fn sample(client: &Storage) -> anyhow::Result<()> {
/// use google_cloud_storage::retry_policy::RecommendedPolicy;
/// use google_cloud_storage::retry_policy::RetryableErrors;
/// use std::time::Duration;
/// use gax::retry_policy::RetryPolicyExt;
/// let response = client
/// .read_object("projects/_/buckets/my-bucket", "my-object")
/// .with_retry_policy(RecommendedPolicy
/// .with_attempt_limit(5)
/// .with_time_limit(Duration::from_secs(10)),
/// .with_retry_policy(
/// RetryableErrors
/// .with_attempt_limit(5)
/// .with_time_limit(Duration::from_secs(10)),
/// )
/// .send()
/// .await?;
Expand Down
2 changes: 1 addition & 1 deletion src/storage/src/storage/read_object/resume_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ async fn start_too_many_transients() -> Result {
.await?;
let err = client
.read_object("projects/_/buckets/test-bucket", "test-object")
.with_retry_policy(crate::retry_policy::RecommendedPolicy.with_attempt_limit(3))
.with_retry_policy(crate::retry_policy::RetryableErrors.with_attempt_limit(3))
.send()
.await
.expect_err("test generates permanent error");
Expand Down
2 changes: 1 addition & 1 deletion src/storage/src/storage/request_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const RESUMABLE_UPLOAD_TARGET_CHUNK: usize = 8 * MIB;

impl RequestOptions {
pub(crate) fn new() -> Self {
let retry_policy = Arc::new(crate::retry_policy::default());
let retry_policy = Arc::new(crate::retry_policy::storage_default());
let backoff_policy = Arc::new(crate::backoff_policy::default());
let retry_throttler = Arc::new(Mutex::new(AdaptiveThrottler::default()));
let read_resume_policy = Arc::new(Recommended);
Expand Down
10 changes: 5 additions & 5 deletions src/storage/src/storage/write_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,6 @@ impl<T, C> WriteObject<T, C> {
/// # Example
/// ```
/// # use google_cloud_storage::client::Storage;
/// # use google_cloud_storage::retry_policy::RecommendedPolicy;
/// # async fn sample(client: &Storage) -> anyhow::Result<()> {
/// use std::time::Duration;
/// use gax::retry_policy::RetryPolicyExt;
Expand All @@ -628,15 +627,16 @@ impl<T, C> WriteObject<T, C> {
/// # Example
/// ```
/// # use google_cloud_storage::client::Storage;
/// # use google_cloud_storage::retry_policy::RecommendedPolicy;
/// # use google_cloud_storage::retry_policy::RetryableErrors;
/// # async fn sample(client: &Storage) -> anyhow::Result<()> {
/// use std::time::Duration;
/// use gax::retry_policy::RetryPolicyExt;
/// let response = client
/// .write_object("projects/_/buckets/my-bucket", "my-object", "hello world")
/// .with_retry_policy(RecommendedPolicy
/// .with_attempt_limit(5)
/// .with_time_limit(Duration::from_secs(10)),
/// .with_retry_policy(
/// RetryableErrors
/// .with_attempt_limit(5)
/// .with_time_limit(Duration::from_secs(90)),
/// )
/// .send_buffered()
/// .await?;
Expand Down
Loading