Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve manual config experience for SDK retries and timeouts #1603

Merged
merged 16 commits into from
Sep 1, 2022
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
64 changes: 63 additions & 1 deletion CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,66 @@
# message = "Fix typos in module documentation for generated crates"
# references = ["smithy-rs#920"]
# meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"}
# author = "rcoh"
# author = "rcoh"

[[aws-sdk-rust]]
message = "`aws_config::RetryConfig` no longer implements `Default`, and its `new` function has been replaced with `standard`."
references = ["smithy-rs#1603", "aws-sdk-rust#586"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "jdisanti"

[[smithy-rs]]
message = "`aws_smithy_types::RetryConfig` no longer implements `Default`, and its `new` function has been replaced with `standard`."
references = ["smithy-rs#1603", "aws-sdk-rust#586"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[aws-sdk-rust]]
message = """
Direct configuration of `aws_config::SdkConfig` now defaults to retries being disabled.
If you're using `aws_config::load_from_env()` or `aws_config::from_env()` to configure
the SDK, then you are NOT affected by this change. If you use `SdkConfig::builder()` to
configure the SDK, then you ARE affected by this change and should set the retry config
on that builder.
"""
references = ["smithy-rs#1603", "aws-sdk-rust#586"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "jdisanti"

[[aws-sdk-rust]]
message = """
Client creation now panics if retries or timeouts are enabled without an async sleep
implementation set on the SDK config.
If you're using the Tokio runtime and have the `rt-tokio` feature enabled (which is enabled by default),
then you shouldn't notice this change at all.
Otherwise, if using something other than Tokio as the async runtime, the `AsyncSleep` trait must be implemented,
and that implementation given to the config builder via the `sleep_impl` method. Alternatively, retry can be
explicitly turned off by setting the retry config to `RetryConfig::disabled()`, which will result in successful
client creation without an async sleep implementation.
"""
references = ["smithy-rs#1603", "aws-sdk-rust#586"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "jdisanti"

[[smithy-rs]]
message = """
Client creation now panics if retries or timeouts are enabled without an async sleep implementation.
If you're using the Tokio runtime and have the `rt-tokio` feature enabled (which is enabled by default),
then you shouldn't notice this change at all.
Otherwise, if using something other than Tokio as the async runtime, the `AsyncSleep` trait must be implemented,
and that implementation given to the config builder via the `sleep_impl` method. Alternatively, retry can be
explicitly turned off by setting `max_attempts` to 1, which will result in successful client creation without an
async sleep implementation.
"""
references = ["smithy-rs#1603", "aws-sdk-rust#586"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"

[[smithy-rs]]
message = """
The `default_async_sleep` method on the `Client` builder has been removed. The default async sleep is
wired up by default if none is provided.
"""
references = ["smithy-rs#1603", "aws-sdk-rust#586"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" }
author = "jdisanti"
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ mod test {
.retry_config()
.await;

let expected_retry_config = RetryConfig::new();
let expected_retry_config = RetryConfig::standard();

assert_eq!(actual_retry_config, expected_retry_config);
// This is redundant but it's really important to make sure that
Expand All @@ -420,7 +420,7 @@ mod test {
.retry_config()
.await;

let expected_retry_config = RetryConfig::new();
let expected_retry_config = RetryConfig::standard();

assert_eq!(actual_retry_config, expected_retry_config)
}
Expand All @@ -447,9 +447,7 @@ retry_mode = standard
.retry_config()
.await;

let expected_retry_config = RetryConfig::new()
.with_max_attempts(1)
.with_retry_mode(RetryMode::Standard);
let expected_retry_config = RetryConfig::standard().with_max_attempts(1);

assert_eq!(actual_retry_config, expected_retry_config)
}
Expand Down Expand Up @@ -480,9 +478,7 @@ retry_mode = standard
.retry_config()
.await;

let expected_retry_config = RetryConfig::new()
.with_max_attempts(42)
.with_retry_mode(RetryMode::Standard);
let expected_retry_config = RetryConfig::standard().with_max_attempts(42);

assert_eq!(actual_retry_config, expected_retry_config)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl Builder {
/// Attempt to create a [RetryConfig](aws_smithy_types::retry::RetryConfig) from following sources in order:
/// 1. [Environment variables](crate::environment::retry_config::EnvironmentVariableRetryConfigProvider)
/// 2. [Profile file](crate::profile::retry_config::ProfileFileRetryConfigProvider)
/// 3. [RetryConfig::default()](aws_smithy_types::retry::RetryConfig::default)
/// 3. [RetryConfig::standard()](aws_smithy_types::retry::RetryConfig::standard)
///
/// Precedence is considered on a per-field basis
///
Expand Down
8 changes: 3 additions & 5 deletions aws/rust-runtime/aws-config/src/environment/retry_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ mod test {
.retry_config_builder()
.unwrap()
.build(),
RetryConfig::new().with_max_attempts(88)
RetryConfig::standard().with_max_attempts(88)
);
}

Expand All @@ -123,7 +123,7 @@ mod test {
.retry_config_builder()
.unwrap()
.build(),
RetryConfig::new().with_retry_mode(RetryMode::Standard)
RetryConfig::standard()
);
}

Expand All @@ -137,9 +137,7 @@ mod test {
.retry_config_builder()
.unwrap()
.build(),
RetryConfig::new()
.with_max_attempts(13)
.with_retry_mode(RetryMode::Standard)
RetryConfig::standard().with_max_attempts(13)
);
}

Expand Down
16 changes: 8 additions & 8 deletions aws/rust-runtime/aws-config/src/imds/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,11 +744,8 @@ impl<T, E> ClassifyResponse<SdkSuccess<T>, SdkError<E>> for ImdsErrorPolicy {

#[cfg(test)]
pub(crate) mod test {
use std::collections::HashMap;
use std::error::Error;
use std::io;
use std::time::{Duration, UNIX_EPOCH};

use crate::imds::client::{Client, EndpointMode, ImdsErrorPolicy};
use crate::provider_config::ProviderConfig;
use aws_smithy_async::rt::sleep::TokioSleep;
use aws_smithy_client::erase::DynConnector;
use aws_smithy_client::test_connection::{capture_request, TestConnection};
Expand All @@ -760,11 +757,12 @@ pub(crate) mod test {
use http::header::USER_AGENT;
use http::Uri;
use serde::Deserialize;
use std::collections::HashMap;
use std::error::Error;
use std::io;
use std::time::{Duration, UNIX_EPOCH};
use tracing_test::traced_test;

use crate::imds::client::{Client, EndpointMode, ImdsErrorPolicy};
use crate::provider_config::ProviderConfig;

const TOKEN_A: &str = "AQAEAFTNrA4eEGx0AQgJ1arIq_Cc-t4tWt3fB0Hd8RKhXlKc5ccvhg==";
const TOKEN_B: &str = "alternatetoken==";

Expand Down Expand Up @@ -918,6 +916,7 @@ pub(crate) mod test {
let client = super::Client::builder()
.configure(
&ProviderConfig::no_configuration()
.with_sleep(TokioSleep::new())
.with_http_connector(DynConnector::new(connection.clone()))
.with_time_source(TimeSource::manual(&time_source)),
)
Expand Down Expand Up @@ -1134,6 +1133,7 @@ pub(crate) mod test {
async fn check(test_case: ImdsConfigTest) {
let (server, watcher) = capture_request(None);
let provider_config = ProviderConfig::no_configuration()
.with_sleep(TokioSleep::new())
.with_env(Env::from(test_case.env))
.with_fs(Fs::from_map(test_case.fs))
.with_http_connector(DynConnector::new(server));
Expand Down
4 changes: 3 additions & 1 deletion aws/rust-runtime/aws-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ mod loader {
/// # use aws_smithy_types::retry::RetryConfig;
/// # async fn create_config() {
/// let config = aws_config::from_env()
/// .retry_config(RetryConfig::new().with_max_attempts(2))
/// .retry_config(RetryConfig::standard().with_max_attempts(2))
/// .load().await;
/// # }
/// ```
Expand Down Expand Up @@ -449,6 +449,7 @@ mod loader {
mod test {
use crate::from_env;
use crate::provider_config::ProviderConfig;
use aws_smithy_async::rt::sleep::TokioSleep;
use aws_smithy_client::erase::DynConnector;
use aws_smithy_client::never::NeverConnector;
use aws_types::credentials::ProvideCredentials;
Expand All @@ -465,6 +466,7 @@ mod loader {
let loader = from_env()
.configure(
ProviderConfig::empty()
.with_sleep(TokioSleep::new())
.with_env(env)
.with_http_connector(DynConnector::new(NeverConnector::new())),
)
Expand Down
3 changes: 3 additions & 0 deletions aws/rust-runtime/aws-config/src/sts/assume_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ impl ProvideCredentials for AssumeRoleProvider {
mod test {
use crate::provider_config::ProviderConfig;
use crate::sts::AssumeRoleProvider;
use aws_smithy_async::rt::sleep::TokioSleep;
use aws_smithy_client::erase::DynConnector;
use aws_smithy_client::test_connection::capture_request;
use aws_smithy_http::body::SdkBody;
Expand All @@ -286,6 +287,7 @@ mod test {
async fn configures_session_length() {
let (server, request) = capture_request(None);
let provider_conf = ProviderConfig::empty()
.with_sleep(TokioSleep::new())
.with_time_source(TimeSource::manual(&ManualTimeSource::new(
UNIX_EPOCH + Duration::from_secs(1234567890 - 120),
)))
Expand Down Expand Up @@ -314,6 +316,7 @@ mod test {
));
let (server, _request) = capture_request(Some(resp));
let provider_conf = ProviderConfig::empty()
.with_sleep(TokioSleep::new())
.with_time_source(TimeSource::manual(&ManualTimeSource::new(
UNIX_EPOCH + Duration::from_secs(1234567890 - 120),
)))
Expand Down
12 changes: 7 additions & 5 deletions aws/rust-runtime/aws-config/src/web_identity_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,22 +259,22 @@ async fn load_credentials(

#[cfg(test)]
mod test {
use crate::provider_config::ProviderConfig;
use crate::test_case::no_traffic_connector;
use crate::web_identity_token::{
Builder, ENV_VAR_ROLE_ARN, ENV_VAR_SESSION_NAME, ENV_VAR_TOKEN_FILE,
};

use aws_sdk_sts::Region;
use aws_types::os_shim_internal::{Env, Fs};

use crate::provider_config::ProviderConfig;
use crate::test_case::no_traffic_connector;
use aws_smithy_async::rt::sleep::TokioSleep;
use aws_types::credentials::CredentialsError;
use aws_types::os_shim_internal::{Env, Fs};
use std::collections::HashMap;

#[tokio::test]
async fn unloaded_provider() {
// empty environment
let conf = ProviderConfig::empty()
.with_sleep(TokioSleep::new())
.with_env(Env::from_slice(&[]))
.with_http_connector(no_traffic_connector())
.with_region(Some(Region::from_static("us-east-1")));
Expand All @@ -297,6 +297,7 @@ mod test {
let provider = Builder::default()
.configure(
&ProviderConfig::empty()
.with_sleep(TokioSleep::new())
.with_region(region)
.with_env(env)
.with_http_connector(no_traffic_connector()),
Expand Down Expand Up @@ -328,6 +329,7 @@ mod test {
let provider = Builder::default()
.configure(
&ProviderConfig::empty()
.with_sleep(TokioSleep::new())
.with_http_connector(no_traffic_connector())
.with_region(Some(Region::new("us-east-1")))
.with_env(env)
Expand Down
32 changes: 30 additions & 2 deletions aws/rust-runtime/aws-types/src/sdk_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ pub struct SdkConfig {
}

/// Builder for AWS Shared Configuration
///
/// _Important:_ Using the `aws-config` crate to configure the SDK is preferred to invoking this
/// builder directly. Using this builder directly won't pull in any AWS recommended default
/// configuration values.
#[derive(Debug, Default)]
pub struct Builder {
app_name: Option<AppName>,
Expand Down Expand Up @@ -127,12 +131,15 @@ impl Builder {

/// Set the retry_config for the builder
///
/// _Note:_ Retries require a sleep implementation in order to work. When enabling retry, make
/// sure to set one with [Self::sleep_impl] or [Self::set_sleep_impl].
///
/// # Examples
/// ```rust
/// use aws_types::SdkConfig;
/// use aws_smithy_types::retry::RetryConfig;
///
/// let retry_config = RetryConfig::new().with_max_attempts(5);
/// let retry_config = RetryConfig::standard().with_max_attempts(5);
/// let config = SdkConfig::builder().retry_config(retry_config).build();
/// ```
pub fn retry_config(mut self, retry_config: RetryConfig) -> Self {
Expand All @@ -142,13 +149,16 @@ impl Builder {

/// Set the retry_config for the builder
///
/// _Note:_ Retries require a sleep implementation in order to work. When enabling retry, make
/// sure to set one with [Self::sleep_impl] or [Self::set_sleep_impl].
///
/// # Examples
/// ```rust
/// use aws_types::sdk_config::{SdkConfig, Builder};
/// use aws_smithy_types::retry::RetryConfig;
///
/// fn disable_retries(builder: &mut Builder) {
/// let retry_config = RetryConfig::new().with_max_attempts(1);
/// let retry_config = RetryConfig::standard().with_max_attempts(1);
/// builder.set_retry_config(Some(retry_config));
/// }
///
Expand All @@ -163,6 +173,10 @@ impl Builder {

/// Set the [`timeout::Config`](aws_smithy_types::timeout::Config) for the builder
///
/// _Note:_ Timeouts require a sleep implementation in order to work.
/// When enabling timeouts, be sure to set one with [Self::sleep_impl] or
/// [Self::set_sleep_impl].
///
/// # Examples
///
/// ```rust
Expand All @@ -184,6 +198,10 @@ impl Builder {

/// Set the [`timeout::Config`](aws_smithy_types::timeout::Config) for the builder
///
/// _Note:_ Timeouts require a sleep implementation in order to work.
/// When enabling timeouts, be sure to set one with [Self::sleep_impl] or
/// [Self::set_sleep_impl].
///
/// # Examples
/// ```rust
/// # use std::time::Duration;
Expand Down Expand Up @@ -211,6 +229,9 @@ impl Builder {
/// Set the sleep implementation for the builder. The sleep implementation is used to create
/// timeout futures.
///
/// _Note:_ If you're using the Tokio runtime, a `TokioSleep` implementation is available in
/// the `aws-smithy-async` crate.
///
/// # Examples
///
/// ```rust
Expand Down Expand Up @@ -238,6 +259,9 @@ impl Builder {
/// Set the sleep implementation for the builder. The sleep implementation is used to create
/// timeout futures.
///
/// _Note:_ If you're using the Tokio runtime, a `TokioSleep` implementation is available in
/// the `aws-smithy-async` crate.
///
/// # Examples
/// ```rust
/// # use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep};
Expand Down Expand Up @@ -405,6 +429,10 @@ impl SdkConfig {
}

/// Config builder
///
/// _Important:_ Using the `aws-config` crate to configure the SDK is preferred to invoking this
/// builder directly. Using this builder directly won't pull in any AWS recommended default
/// configuration values.
pub fn builder() -> Builder {
Builder::default()
}
Expand Down
Loading