From 722f31359427dd164f95efe00d5b6cd34a1ff39f Mon Sep 17 00:00:00 2001 From: Zelda Hessler Date: Wed, 24 Nov 2021 13:15:03 -0600 Subject: [PATCH] add: example showing how to set all currently supported timeouts (#890) * add: example of how to set all currently supported timeouts * update: SDK_CHANGELOG.md * Apply suggestions from code review Co-authored-by: Russell Cohen * update: docs based on PR suggestions Co-authored-by: Russell Cohen --- aws/SDK_CHANGELOG.md | 1 + aws/sdk/examples/setting_timeouts/Cargo.toml | 14 ++++ aws/sdk/examples/setting_timeouts/src/main.rs | 79 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 aws/sdk/examples/setting_timeouts/Cargo.toml create mode 100644 aws/sdk/examples/setting_timeouts/src/main.rs diff --git a/aws/SDK_CHANGELOG.md b/aws/SDK_CHANGELOG.md index 906c2a2fd..39cd0a883 100644 --- a/aws/SDK_CHANGELOG.md +++ b/aws/SDK_CHANGELOG.md @@ -10,6 +10,7 @@ vNext (Month Day, Year) - `SdkError` now includes a variant `TimeoutError` for when a request times out (smithy-rs#885) - Improve docs on `aws-smithy-client` (smithy-rs#855) - Fix http-body dependency version (smithy-rs#883, aws-sdk-rust#305) +- [Added a new example showing how to set all currently supported timeouts](./sdk/examples/setting_timeouts/src/main.rs) - Add a new check so that the SDK doesn't emit an irrelevant `$HOME` dir warning when running in a Lambda (aws-sdk-rust#307) **Breaking changes** diff --git a/aws/sdk/examples/setting_timeouts/Cargo.toml b/aws/sdk/examples/setting_timeouts/Cargo.toml new file mode 100644 index 000000000..744f5f2ef --- /dev/null +++ b/aws/sdk/examples/setting_timeouts/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "setting_timeouts" +version = "0.1.0" +authors = ["Zelda Hessler zhessler@amazon.com>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aws-config = { path = "../../build/aws-sdk/sdk/aws-config" } +aws-sdk-s3 = { package = "aws-sdk-s3", path = "../../build/aws-sdk/sdk/s3" } +aws-smithy-client = { path = "../../build/aws-sdk/sdk/aws-smithy-client" } +tokio = { version = "1", features = ["full"] } +tracing-subscriber = "0.2.18" diff --git a/aws/sdk/examples/setting_timeouts/src/main.rs b/aws/sdk/examples/setting_timeouts/src/main.rs new file mode 100644 index 000000000..988c9519d --- /dev/null +++ b/aws/sdk/examples/setting_timeouts/src/main.rs @@ -0,0 +1,79 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +use aws_config::TimeoutConfig; +use aws_smithy_client::{conns, erase::DynConnector, hyper_ext, timeout}; +use std::time::Duration; + +/// The SDK divides timeouts into two groups: +/// +/// - Timeouts that occur at the client level _(outside of a `Connector`)_, hereafter referred to +/// as "first group" timeouts +/// - Timeouts that occur at the connector level _(inside a `Connector`)_, hereafter referred to +/// as "second group" timeouts +/// +/// In the future, all timeouts will be set in the same way. In the present, these two groups of +/// timeouts must be set separately. This app provides an example of how to set both groups of +/// timeouts. +/// +/// **TLS negotiation timeouts will eventually be included with the second group but are +/// not yet supported** +/// +/// The timeouts in this example are set to one second which may or may not be fast enough to +/// trigger them based on your connection speeds. If you want to ensure a timeout gets triggered +/// so you can see what the resulting error looks like, change the durations from +/// `Duration::from_secs(2)` to `Duration::from_millis(2)`. +/// +/// You could _also_ trigger the timeouts by replacing the HTTPS connector _(`conns::https()`)_ +/// with a `NeverConnector`. That's how we manually trigger timeouts when writing tests. +#[tokio::main] +async fn main() -> Result<(), aws_sdk_s3::Error> { + tracing_subscriber::fmt::init(); + + // Here we set our "first group" timeouts + let request_timeout_config = TimeoutConfig::new() + // This timeout acts at the "Request to a service" level. When the SDK makes a request to a + // service, that "request" may actually comprise of several HTTP requests in order to retry + // failures that are likely spurious or to refresh credentials. + .with_api_call_timeout(Some(Duration::from_secs(2))) + // This timeout acts at the "HTTP request" level and will set a separate timeout for each + // HTTP request made as part of a "service request" + .with_api_call_attempt_timeout(Some(Duration::from_secs(2))); + + // Timeouts can also be defined in your environment or AWS profile but in this example we + // overrule any that happen to be set + let shared_config = aws_config::from_env() + .timeout_config(request_timeout_config) + .load() + .await; + + // Here we set our "second group" timeouts + let http_timeout_config = timeout::Settings::new() + // A limit on the amount of time an application takes to attempt to read the first byte over + // an established, open connection after write request. + // Also known as the "time to first byte" timeout + .with_read_timeout(Duration::from_secs(2)) + // A limit on the amount of time after making an initial connect attempt on a socket to + // complete the connect-handshake + .with_connect_timeout(Duration::from_secs(2)); + + // These timeouts must be passed to create the `Connector` that will handle our HTTP requests. + // If a timeout needs to be changed after this, we'd have to create a new `Connector`. + let conn = DynConnector::new( + hyper_ext::Adapter::builder() + .timeout(&http_timeout_config) + .build(conns::https()), + ); + let s3_config = aws_sdk_s3::Config::from(&shared_config); + let client = aws_sdk_s3::Client::from_conf_conn(s3_config, conn); + + let resp = client.list_buckets().send().await?; + + for bucket in resp.buckets().unwrap_or_default() { + println!("bucket: {:?}", bucket.name().unwrap_or_default()) + } + + Ok(()) +} -- GitLab