Commit 4dfc7e90 authored by AWS SDK Rust Bot's avatar AWS SDK Rust Bot
Browse files

[smithy-rs] Rollup of 10 commits



Includes commits:
  7b30ffcb HTTP Wrapper Type RFC & Implementation (#2912)
  441b05d5 Small update to the production guidance wording (#3049)
  38375a5a Address some trivial TODO comments (#3040)
  547b6317 Remove temporary test customizations (#3044)
  8bfc4c61 Run `--all` in precommit (#3048)
  e61fb6f0 Update `toSnakeCase` to better handle plurals, version numbers, and other pathological cases (#3037)
  0f908065 Remove `CaptureSmithyConnectionWrapper` (#3045)
  d1ad9373 Remove commented test (#3051)
  96a9f844 implement user-configurable retry classifiers (#2977)
  e06a57d3 add retry classifier customization RFC (#3018)

Co-authored-by: default avatarJohn DiSanti <jdisanti@amazon.com>
Co-authored-by: default avatarRussell Cohen <rcoh@amazon.com>
Co-authored-by: default avatarZelda Hessler <zhessler@amazon.com>
parent ca86e98f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ To update it, edit the `aws/SDK_README.md.hb` Handlebars template in that reposi

This repo contains the new AWS SDK for Rust (the SDK) and its [public roadmap](https://github.com/orgs/awslabs/projects/50/views/1).

**Please Note: The SDK is currently released as a developer preview and is intended strictly for feedback purposes only. Do not use this SDK for production workloads.**
**Please Note**: The SDK is currently released as a developer preview, without support or assistance for use on production workloads. Any use in production is at your own risk.

The SDK is code generated from [Smithy models](https://awslabs.github.io/smithy/) that represent each AWS service. The code used to generate the SDK can be found in [smithy-rs](https://github.com/awslabs/smithy-rs).

+8 −8
Original line number Diff line number Diff line
@@ -88,16 +88,16 @@ impl Client {
    /// If you experience this panic, it can be fixed by setting the `sleep_impl`, or by disabling
    /// retries and timeouts.
    pub fn from_conf(conf: crate::Config) -> Self {
        let retry_config = conf
        let has_retry_config = conf
            .retry_config()
            .cloned()
            .unwrap_or_else(::aws_smithy_types::retry::RetryConfig::disabled);
        let timeout_config = conf
            .map(::aws_smithy_types::retry::RetryConfig::has_retry)
            .unwrap_or_default();
        let has_timeout_config = conf
            .timeout_config()
            .cloned()
            .unwrap_or_else(::aws_smithy_types::timeout::TimeoutConfig::disabled);
            .map(::aws_smithy_types::timeout::TimeoutConfig::has_timeouts)
            .unwrap_or_default();
        let sleep_impl = conf.sleep_impl();
        if (retry_config.has_retry() || timeout_config.has_timeouts()) && sleep_impl.is_none() {
        if (has_retry_config || has_timeout_config) && sleep_impl.is_none() {
            panic!(
                "An async sleep implementation is required for retries or timeouts to work. \
                                 Set the `sleep_impl` on the Config passed into this function to fix this panic."
+0 −90
Original line number Diff line number Diff line
@@ -118,94 +118,4 @@ impl<T, E, B> CustomizableOperation<T, E, B> {

        self.customizable_send.send(config_override).await
    }

    #[doc(hidden)]
    // This is a temporary method for testing. NEVER use it in production
    pub fn request_time_for_tests(self, request_time: ::std::time::SystemTime) -> Self {
        self.runtime_plugin(
            ::aws_smithy_runtime_api::client::runtime_plugin::StaticRuntimePlugin::new().with_runtime_components(
                ::aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder::new("request_time_for_tests")
                    .with_time_source(Some(::aws_smithy_async::time::StaticTimeSource::new(request_time))),
            ),
        )
    }

    #[doc(hidden)]
    // This is a temporary method for testing. NEVER use it in production
    pub fn user_agent_for_tests(mut self) -> Self {
        let interceptor = crate::client::customize::TestParamsSetterInterceptor::new(
            |context: &mut ::aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut<'_>,
             _: &mut ::aws_smithy_types::config_bag::ConfigBag| {
                let headers = context.request_mut().headers_mut();
                let user_agent = ::aws_http::user_agent::AwsUserAgent::for_tests();
                headers.insert(::http::header::USER_AGENT, ::http::HeaderValue::try_from(user_agent.ua_header()).unwrap());
                headers.insert(
                    ::http::HeaderName::from_static("x-amz-user-agent"),
                    ::http::HeaderValue::try_from(user_agent.aws_ua_header()).unwrap(),
                );
            },
        );
        self.interceptors
            .push(::aws_smithy_runtime_api::client::interceptors::SharedInterceptor::new(interceptor));
        self
    }

    #[doc(hidden)]
    // This is a temporary method for testing. NEVER use it in production
    pub fn remove_invocation_id_for_tests(mut self) -> Self {
        let interceptor = crate::client::customize::TestParamsSetterInterceptor::new(
            |context: &mut ::aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut<'_>,
             _: &mut ::aws_smithy_types::config_bag::ConfigBag| {
                context.request_mut().headers_mut().remove("amz-sdk-invocation-id");
            },
        );
        self.interceptors
            .push(::aws_smithy_runtime_api::client::interceptors::SharedInterceptor::new(interceptor));
        self
    }
}

mod test_params_setter_interceptor {
    use aws_smithy_runtime_api::box_error::BoxError;
    use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut;
    use aws_smithy_runtime_api::client::interceptors::Interceptor;
    use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
    use aws_smithy_types::config_bag::ConfigBag;
    use std::fmt;

    pub(super) struct TestParamsSetterInterceptor<F> {
        f: F,
    }

    impl<F> fmt::Debug for TestParamsSetterInterceptor<F> {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(f, "TestParamsSetterInterceptor")
        }
    }

    impl<F> TestParamsSetterInterceptor<F> {
        pub fn new(f: F) -> Self {
            Self { f }
        }
    }

    impl<F> Interceptor for TestParamsSetterInterceptor<F>
    where
        F: Fn(&mut BeforeTransmitInterceptorContextMut<'_>, &mut ConfigBag) + Send + Sync + 'static,
    {
        fn name(&self) -> &'static str {
            "TestParamsSetterInterceptor"
        }

        fn modify_before_signing(
            &self,
            context: &mut BeforeTransmitInterceptorContextMut<'_>,
            _runtime_components: &RuntimeComponents,
            cfg: &mut ConfigBag,
        ) -> Result<(), BoxError> {
            (self.f)(context, cfg);
            Ok(())
        }
    }
}
use test_params_setter_interceptor::TestParamsSetterInterceptor;
+202 −2
Original line number Diff line number Diff line
@@ -93,6 +93,10 @@ impl Config {
    pub fn time_source(&self) -> ::std::option::Option<::aws_smithy_async::time::SharedTimeSource> {
        self.runtime_components.time_source()
    }
    /// Returns retry classifiers currently registered by the user.
    pub fn retry_classifiers(&self) -> impl Iterator<Item = ::aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier> + '_ {
        self.runtime_components.retry_classifiers()
    }
    /// Returns the name of the app that is using the client, if it was provided.
    ///
    /// This _optional_ name is used to identify the application in the user agent that
@@ -572,6 +576,200 @@ impl Builder {
        self.runtime_components.set_time_source(time_source);
        self
    }
    /// Add type implementing [`ClassifyRetry`](::aws_smithy_runtime_api::client::retries::classifiers::ClassifyRetry) that will be used by the
    /// [`RetryStrategy`](::aws_smithy_runtime_api::client::retries::RetryStrategy) to determine what responses should be retried.
    ///
    /// A retry classifier configured by this method will run according to its [priority](::aws_smithy_runtime_api::client::retries::classifiers::RetryClassifierPriority).
    ///
    /// # Examples
    /// ```no_run
    /// # #[cfg(test)]
    /// # mod tests {
    /// # #[test]
    /// # fn example() {
    /// use aws_smithy_runtime_api::client::interceptors::context::InterceptorContext;
    /// use aws_smithy_runtime_api::client::orchestrator::OrchestratorError;
    /// use aws_smithy_runtime_api::client::retries::classifiers::{
    ///     ClassifyRetry, RetryAction, RetryClassifierPriority,
    /// };
    /// use aws_smithy_types::error::metadata::ProvideErrorMetadata;
    /// use aws_smithy_types::retry::ErrorKind;
    /// use std::error::Error as StdError;
    /// use std::marker::PhantomData;
    /// use aws_sdk_accessanalyzer::config::Config;
    /// # struct SomeOperationError {}
    ///
    /// const RETRYABLE_ERROR_CODES: &[&str] = [
    ///     // List error codes to be retried here...
    /// ];
    ///
    /// // When classifying at an operation's error type, classifiers require a generic parameter.
    /// // When classifying the HTTP response alone, no generic is needed.
    /// #[derive(Debug, Default)]
    /// pub struct ErrorCodeClassifier<E> {
    ///     _inner: PhantomData<E>,
    /// }
    ///
    /// impl<E> ExampleErrorCodeClassifier<E> {
    ///     pub fn new() -> Self {
    ///         Self {
    ///             _inner: PhantomData,
    ///         }
    ///     }
    /// }
    ///
    /// impl<E> ClassifyRetry for ExampleErrorCodeClassifier<E>
    /// where
    ///     // Adding a trait bound for ProvideErrorMetadata allows us to inspect the error code.
    ///     E: StdError + ProvideErrorMetadata + Send + Sync + 'static,
    /// {
    ///     fn classify_retry(&self, ctx: &InterceptorContext) -> RetryAction {
    ///         // Check for a result
    ///         let output_or_error = ctx.output_or_error();
    ///         // Check for an error
    ///         let error = match output_or_error {
    ///             Some(Ok(_)) | None => return RetryAction::NoActionIndicated,
    ///               Some(Err(err)) => err,
    ///         };
    ///
    ///         // Downcast the generic error and extract the code
    ///         let error_code = OrchestratorError::as_operation_error(error)
    ///             .and_then(|err| err.downcast_ref::<E>())
    ///             .and_then(|err| err.code());
    ///
    ///         // If this error's code is in our list, return an action that tells the RetryStrategy to retry this request.
    ///         if let Some(error_code) = error_code {
    ///             if RETRYABLE_ERROR_CODES.contains(&error_code) {
    ///                 return RetryAction::transient_error();
    ///             }
    ///         }
    ///
    ///         // Otherwise, return that no action is indicated i.e. that this classifier doesn't require a retry.
    ///         // Another classifier may still classify this response as retryable.
    ///         RetryAction::NoActionIndicated
    ///     }
    ///
    ///     fn name(&self) -> &'static str { "Example Error Code Classifier" }
    /// }
    ///
    /// let config = Config::builder()
    ///     .retry_classifier(ExampleErrorCodeClassifier::<SomeOperationError>::new())
    ///     .build();
    /// # }
    /// # }
    /// ```
    pub fn retry_classifier(
        mut self,
        retry_classifier: impl ::aws_smithy_runtime_api::client::retries::classifiers::ClassifyRetry + 'static,
    ) -> Self {
        self.push_retry_classifier(::aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier::new(
            retry_classifier,
        ));
        self
    }

    /// Add a [`SharedRetryClassifier`](::aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier) that will be used by the
    /// [`RetryStrategy`](::aws_smithy_runtime_api::client::retries::RetryStrategy) to determine what responses should be retried.
    ///
    /// A retry classifier configured by this method will run according to its priority.
    ///
    /// # Examples
    /// ```no_run
    /// # #[cfg(test)]
    /// # mod tests {
    /// # #[test]
    /// # fn example() {
    /// use aws_smithy_runtime_api::client::interceptors::context::InterceptorContext;
    /// use aws_smithy_runtime_api::client::orchestrator::OrchestratorError;
    /// use aws_smithy_runtime_api::client::retries::classifiers::{
    ///     ClassifyRetry, RetryAction, RetryClassifierPriority,
    /// };
    /// use aws_smithy_types::error::metadata::ProvideErrorMetadata;
    /// use aws_smithy_types::retry::ErrorKind;
    /// use std::error::Error as StdError;
    /// use std::marker::PhantomData;
    /// use aws_sdk_accessanalyzer::config::{Builder, Config};
    /// # struct SomeOperationError {}
    ///
    /// const RETRYABLE_ERROR_CODES: &[&str] = [
    ///     // List error codes to be retried here...
    /// ];
    /// fn set_example_error_code_classifier(builder: &mut Builder) {
    ///     // When classifying at an operation's error type, classifiers require a generic parameter.
    ///     // When classifying the HTTP response alone, no generic is needed.
    ///     #[derive(Debug, Default)]
    ///     pub struct ExampleErrorCodeClassifier<E> {
    ///         _inner: PhantomData<E>,
    ///     }
    ///
    ///     impl<E> ExampleErrorCodeClassifier<E> {
    ///         pub fn new() -> Self {
    ///             Self {
    ///                 _inner: PhantomData,
    ///             }
    ///         }
    ///     }
    ///
    ///     impl<E> ClassifyRetry for ExampleErrorCodeClassifier<E>
    ///     where
    ///         // Adding a trait bound for ProvideErrorMetadata allows us to inspect the error code.
    ///         E: StdError + ProvideErrorMetadata + Send + Sync + 'static,
    ///     {
    ///         fn classify_retry(&self, ctx: &InterceptorContext) -> RetryAction {
    ///             // Check for a result
    ///             let output_or_error = ctx.output_or_error();
    ///             // Check for an error
    ///             let error = match output_or_error {
    ///                 Some(Ok(_)) | None => return RetryAction::NoActionIndicated,
    ///                   Some(Err(err)) => err,
    ///             };
    ///
    ///             // Downcast the generic error and extract the code
    ///             let error_code = OrchestratorError::as_operation_error(error)
    ///                 .and_then(|err| err.downcast_ref::<E>())
    ///                 .and_then(|err| err.code());
    ///
    ///             // If this error's code is in our list, return an action that tells the RetryStrategy to retry this request.
    ///             if let Some(error_code) = error_code {
    ///                 if RETRYABLE_ERROR_CODES.contains(&error_code) {
    ///                     return RetryAction::transient_error();
    ///                 }
    ///             }
    ///
    ///             // Otherwise, return that no action is indicated i.e. that this classifier doesn't require a retry.
    ///             // Another classifier may still classify this response as retryable.
    ///             RetryAction::NoActionIndicated
    ///         }
    ///
    ///         fn name(&self) -> &'static str { "Example Error Code Classifier" }
    ///     }
    ///
    ///     builder.push_retry_classifier(ExampleErrorCodeClassifier::<SomeOperationError>::new())
    /// }
    ///
    /// let mut builder = Config::builder();
    /// set_example_error_code_classifier(&mut builder);
    /// let config = builder.build();
    /// # }
    /// # }
    /// ```
    pub fn push_retry_classifier(
        &mut self,
        retry_classifier: ::aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier,
    ) -> &mut Self {
        self.runtime_components.push_retry_classifier(retry_classifier);
        self
    }

    /// Set [`SharedRetryClassifier`](::aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier)s for the builder, replacing any that
    /// were previously set.
    pub fn set_retry_classifiers(
        &mut self,
        retry_classifiers: impl IntoIterator<Item = ::aws_smithy_runtime_api::client::retries::classifiers::SharedRetryClassifier>,
    ) -> &mut Self {
        self.runtime_components.set_retry_classifiers(retry_classifiers.into_iter());
        self
    }
    /// Sets the name of the app that is using the client.
    ///
    /// This _optional_ name is used to identify the application in the user agent that
@@ -705,11 +903,12 @@ impl Builder {
    #[cfg(any(feature = "test-util", test))]
    #[allow(unused_mut)]
    /// Apply test defaults to the builder
    pub fn set_test_defaults(&mut self) -> &mut Self {
    pub fn apply_test_defaults(&mut self) -> &mut Self {
        self.set_idempotency_token_provider(Some("00000000-0000-4000-8000-000000000000".into()));
        self.set_time_source(::std::option::Option::Some(::aws_smithy_async::time::SharedTimeSource::new(
            ::aws_smithy_async::time::StaticTimeSource::new(::std::time::UNIX_EPOCH + ::std::time::Duration::from_secs(1234567890)),
        )));
        self.config.store_put(::aws_http::user_agent::AwsUserAgent::for_tests());
        self.set_credentials_provider(Some(::aws_credential_types::provider::SharedCredentialsProvider::new(
            ::aws_credential_types::Credentials::for_tests(),
        )));
@@ -719,7 +918,7 @@ impl Builder {
    #[allow(unused_mut)]
    /// Apply test defaults to the builder
    pub fn with_test_defaults(mut self) -> Self {
        self.set_test_defaults();
        self.apply_test_defaults();
        self
    }
    /// Builds a [`Config`].
@@ -826,6 +1025,7 @@ impl ServiceRuntimePlugin {
        let config = { None };
        let mut runtime_components = ::aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder::new("ServiceRuntimePlugin");
        runtime_components.push_interceptor(::aws_smithy_runtime::client::http::connection_poisoning::ConnectionPoisoningInterceptor::new());
        runtime_components.push_retry_classifier(::aws_smithy_runtime::client::retries::classifiers::HttpStatusCodeClassifier::default());
        runtime_components.push_interceptor(::aws_runtime::service_clock_skew::ServiceClockSkewInterceptor::new());
        runtime_components.push_interceptor(::aws_runtime::request_info::RequestInfoInterceptor::new());
        runtime_components.push_interceptor(::aws_runtime::user_agent::UserAgentInterceptor::new());
+2 −2
Original line number Diff line number Diff line
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
pub use ::aws_smithy_runtime_api::client::retries::ClassifyRetry;
pub use ::aws_smithy_runtime_api::client::retries::RetryReason;
pub use ::aws_smithy_runtime_api::client::retries::classifiers::ClassifyRetry;
pub use ::aws_smithy_runtime_api::client::retries::classifiers::RetryAction;
pub use ::aws_smithy_runtime_api::client::retries::ShouldAttempt;

pub use ::aws_smithy_runtime::client::retries::RetryPartition;
Loading