Unverified Commit 722f3135 authored by Zelda Hessler's avatar Zelda Hessler Committed by GitHub
Browse files

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: default avatarRussell Cohen <rcoh@amazon.com>

* update: docs based on PR suggestions

Co-authored-by: default avatarRussell Cohen <rcoh@amazon.com>
parent fbb4bca6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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**
+14 −0
Original line number Diff line number Diff line
[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"
+79 −0
Original line number Diff line number Diff line
/*
 * 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(())
}