diff --git a/aws/rust-runtime/aws-inlineable/Cargo.toml b/aws/rust-runtime/aws-inlineable/Cargo.toml index 4a6630ea6fa8124392ff1d2efc3202498480b85f..0b8141b092af47a4116632f1528b1d7e59c9c62a 100644 --- a/aws/rust-runtime/aws-inlineable/Cargo.toml +++ b/aws/rust-runtime/aws-inlineable/Cargo.toml @@ -22,8 +22,8 @@ aws-smithy-checksums = { path = "../../../rust-runtime/aws-smithy-checksums" } aws-smithy-client = { path = "../../../rust-runtime/aws-smithy-client" } aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" } aws-smithy-http-tower = { path = "../../../rust-runtime/aws-smithy-http-tower" } -aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api" } -aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime" } +aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } +aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client"] } aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" } aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" } aws-types = { path = "../aws-types" } diff --git a/aws/rust-runtime/aws-runtime/Cargo.toml b/aws/rust-runtime/aws-runtime/Cargo.toml index 9600d1f0a9756ef47fdfc1a48761e3a8931a1f4a..fddff0c9fe4f8f9e672a9384a053495d26104fc3 100644 --- a/aws/rust-runtime/aws-runtime/Cargo.toml +++ b/aws/rust-runtime/aws-runtime/Cargo.toml @@ -18,7 +18,6 @@ aws-sigv4 = { path = "../aws-sigv4" } aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" } aws-smithy-eventstream = { path = "../../../rust-runtime/aws-smithy-eventstream", optional = true } aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" } -aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client"] } aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" } aws-types = { path = "../aws-types" } diff --git a/aws/rust-runtime/aws-runtime/src/lib.rs b/aws/rust-runtime/aws-runtime/src/lib.rs index a86f74d05635ab8015cc9dc05a9ac356834e5273..6ad3cec35673dc34915e435fd6d0231958a4c9cd 100644 --- a/aws/rust-runtime/aws-runtime/src/lib.rs +++ b/aws/rust-runtime/aws-runtime/src/lib.rs @@ -33,3 +33,6 @@ pub mod invocation_id; /// Supporting code for request metadata headers in the AWS SDK. pub mod request_info; + +/// Interceptor that determines the clock skew between the client and service. +pub mod service_clock_skew; diff --git a/aws/rust-runtime/aws-runtime/src/request_info.rs b/aws/rust-runtime/aws-runtime/src/request_info.rs index fcea15ef51db1df13d3de163d2ebd481bf42b754..ab3311f338d66747fe78f97fdfd2e46e8d1e7436 100644 --- a/aws/rust-runtime/aws-runtime/src/request_info.rs +++ b/aws/rust-runtime/aws-runtime/src/request_info.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_runtime::client::orchestrator::interceptors::ServiceClockSkew; +use crate::service_clock_skew::ServiceClockSkew; 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; diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs b/aws/rust-runtime/aws-runtime/src/service_clock_skew.rs similarity index 91% rename from rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs rename to aws/rust-runtime/aws-runtime/src/service_clock_skew.rs index 16cb5d18b60dfebc345ab405dff8f2dafdf42ce3..7ada75c2bfef3154887199d0fc4323c9e4ebc38c 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs +++ b/aws/rust-runtime/aws-runtime/src/service_clock_skew.rs @@ -12,9 +12,10 @@ use aws_smithy_types::date_time::Format; use aws_smithy_types::DateTime; use std::time::{Duration, SystemTime}; +/// Amount of clock skew between the client and the service. #[derive(Debug, Clone)] #[non_exhaustive] -pub struct ServiceClockSkew { +pub(crate) struct ServiceClockSkew { inner: Duration, } @@ -22,10 +23,6 @@ impl ServiceClockSkew { fn new(inner: Duration) -> Self { Self { inner } } - - pub fn skew(&self) -> Duration { - self.inner - } } impl Storable for ServiceClockSkew { @@ -38,11 +35,13 @@ impl From for Duration { } } +/// Interceptor that determines the clock skew between the client and service. #[derive(Debug, Default)] #[non_exhaustive] -pub struct ServiceClockSkewInterceptor {} +pub struct ServiceClockSkewInterceptor; impl ServiceClockSkewInterceptor { + /// Creates a new `ServiceClockSkewInterceptor`. pub fn new() -> Self { Self::default() } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RetryInformationHeaderDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RetryInformationHeaderDecorator.kt index 221c2ec4301dc0f0dd3fef2082dce0c9d0e0dc24..e3d9fb2176acd91cea75ad50f022f668a02cd00a 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RetryInformationHeaderDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RetryInformationHeaderDecorator.kt @@ -12,7 +12,6 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.ServiceRunti import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.util.letIf class RetryInformationHeaderDecorator : ClientCodegenDecorator { @@ -31,7 +30,6 @@ class RetryInformationHeaderDecorator : ClientCodegenDecorator { private class AddRetryInformationHeaderInterceptors(codegenContext: ClientCodegenContext) : ServiceRuntimePluginCustomization() { private val runtimeConfig = codegenContext.runtimeConfig - private val smithyRuntime = RuntimeType.smithyRuntime(runtimeConfig) private val awsRuntime = AwsRuntimeType.awsRuntime(runtimeConfig) override fun section(section: ServiceRuntimePluginSection): Writable = writable { @@ -40,7 +38,7 @@ private class AddRetryInformationHeaderInterceptors(codegenContext: ClientCodege section.registerInterceptor(runtimeConfig, this) { rust( "#T::new()", - smithyRuntime.resolve("client::orchestrator::interceptors::ServiceClockSkewInterceptor"), + awsRuntime.resolve("service_clock_skew::ServiceClockSkewInterceptor"), ) } diff --git a/rust-runtime/aws-smithy-runtime/src/client.rs b/rust-runtime/aws-smithy-runtime/src/client.rs index 31722c94d45baf3ed10d667703882df8ba60de56..629b558c321d45c46e3fa42508525e5b9e31dd47 100644 --- a/rust-runtime/aws-smithy-runtime/src/client.rs +++ b/rust-runtime/aws-smithy-runtime/src/client.rs @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +/// Smithy auth scheme implementations. pub mod auth; /// Smithy code related to connectors and connections. diff --git a/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs b/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs index 8593f0d9a5cfb2953c9ba5668999972fa88b2ed6..1e0efcd1c43e612524e756a9c8d173880a17975c 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/auth/http.rs @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +//! Auth scheme implementations for HTTP API Key, Basic Auth, Bearer Token, and Digest auth. + use aws_smithy_http::query_writer::QueryWriter; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::auth::http::{ @@ -24,7 +26,9 @@ use http::HeaderValue; /// Destination for the API key #[derive(Copy, Clone, Debug)] pub enum ApiKeyLocation { + /// Place the API key in the URL query parameters Query, + /// Place the API key in the request headers Header, } diff --git a/rust-runtime/aws-smithy-runtime/src/client/auth/no_auth.rs b/rust-runtime/aws-smithy-runtime/src/client/auth/no_auth.rs index 115f78b8e8c17281f0b9e142cb70db42d7631c29..ebda0f69432a0cbef852e18f8bf46122736d7357 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/auth/no_auth.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/auth/no_auth.rs @@ -19,6 +19,7 @@ use aws_smithy_runtime_api::client::runtime_plugin::RuntimePlugin; use aws_smithy_types::config_bag::ConfigBag; use std::borrow::Cow; +/// Auth scheme ID for "no auth". pub const NO_AUTH_SCHEME_ID: AuthSchemeId = AuthSchemeId::new("no_auth"); /// A [`RuntimePlugin`] that registers a "no auth" identity resolver and auth scheme. @@ -36,6 +37,7 @@ impl Default for NoAuthRuntimePlugin { } impl NoAuthRuntimePlugin { + /// Creates a new `NoAuthRuntimePlugin`. pub fn new() -> Self { Self( RuntimeComponentsBuilder::new("NoAuthRuntimePlugin") @@ -54,12 +56,19 @@ impl RuntimePlugin for NoAuthRuntimePlugin { } } +/// The "no auth" auth scheme. +/// +/// The orchestrator requires an auth scheme, so Smithy's `@optionalAuth` trait is implemented +/// by placing a "no auth" auth scheme at the end of the auth scheme options list so that it is +/// used if there's no identity resolver available for the other auth schemes. It's also used +/// for models that don't have auth at all. #[derive(Debug, Default)] pub struct NoAuthScheme { signer: NoAuthSigner, } impl NoAuthScheme { + /// Creates a new `NoAuthScheme`. pub fn new() -> Self { Self::default() } diff --git a/rust-runtime/aws-smithy-runtime/src/client/config_override.rs b/rust-runtime/aws-smithy-runtime/src/client/config_override.rs index c69770a974873113d5b7ecfd471dbef7af26b0c8..07886a9526db21ca94e3ae04f8e923243c19fdbb 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/config_override.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/config_override.rs @@ -10,11 +10,13 @@ use aws_smithy_types::config_bag::{ }; macro_rules! component { - ($typ:ty, $accessor:ident, $latest_accessor:ident) => { + ($typ:ty, $accessor:ident, $latest_accessor:ident, $doc:tt) => { + #[doc = $doc] pub fn $accessor(&self) -> Option<$typ> { fallback_component!(self, $typ, $accessor) } + #[doc = $doc] pub fn $latest_accessor(&self) -> Option<$typ> { latest_component!(self, $typ, $accessor) } @@ -162,7 +164,12 @@ impl<'a> Resolver<'a> { } // Add additional component methods as needed - component!(SharedAsyncSleep, sleep_impl, latest_sleep_impl); + component!( + SharedAsyncSleep, + sleep_impl, + latest_sleep_impl, + "The async sleep implementation." + ); fn config(&self) -> &Layer { match &self.inner { diff --git a/rust-runtime/aws-smithy-runtime/src/client/connectors.rs b/rust-runtime/aws-smithy-runtime/src/client/connectors.rs index 445425680b4eeb61b6b6ca3eed4a10d0ceb2037b..75da05271e8ac67248454d9f23199160267b0d47 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/connectors.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/connectors.rs @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +/// Interceptor for connection poisoning. pub mod connection_poisoning; + #[cfg(feature = "test-util")] pub mod test_util; @@ -17,6 +19,11 @@ pub mod adapter { use aws_smithy_runtime_api::client::orchestrator::{BoxFuture, HttpRequest, HttpResponse}; use std::sync::{Arc, Mutex}; + /// Adapts a [`DynConnector`] to the [`HttpConnector`] trait. + /// + /// This is a temporary adapter that allows the old-style tower-based connectors to + /// work with the new non-tower based architecture of the generated clients. + /// It will be removed in a future release. #[derive(Debug)] pub struct DynConnectorAdapter { // `DynConnector` requires `&mut self`, so we need interior mutability to adapt to it @@ -24,6 +31,7 @@ pub mod adapter { } impl DynConnectorAdapter { + /// Creates a new `DynConnectorAdapter`. pub fn new(dyn_connector: DynConnector) -> Self { Self { dyn_connector: Arc::new(Mutex::new(dyn_connector)), diff --git a/rust-runtime/aws-smithy-runtime/src/client/connectors/connection_poisoning.rs b/rust-runtime/aws-smithy-runtime/src/client/connectors/connection_poisoning.rs index 7c1517550de8f9ca563af8a4f1d949f3aa880de5..5f6f4e78623565b0caa9f510134b886e4898063e 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/connectors/connection_poisoning.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/connectors/connection_poisoning.rs @@ -34,6 +34,7 @@ use tracing::{debug, error}; pub struct ConnectionPoisoningInterceptor {} impl ConnectionPoisoningInterceptor { + /// Create a new `ConnectionPoisoningInterceptor`. pub fn new() -> Self { Self::default() } @@ -99,28 +100,32 @@ impl Interceptor for ConnectionPoisoningInterceptor { } } -// TODO(enableNewSmithyRuntimeLaunch) We won't need this once we absorb aws_smithy_http into the -// new runtime crate. +// TODO(enableNewSmithyRuntimeCleanup): A storable wrapper won't be needed anymore once we absorb aws_smithy_http into the new runtime crate. +/// A wrapper around CaptureSmithyConnection that implements `Storable` so that it can be added to the `ConfigBag`. #[derive(Clone, Default)] pub struct CaptureSmithyConnectionWrapper { inner: CaptureSmithyConnection, } impl CaptureSmithyConnectionWrapper { + /// Creates a new `CaptureSmithyConnectionWrapper`. pub fn new() -> Self { Self { inner: CaptureSmithyConnection::new(), } } + /// Returns a reference to the inner `CaptureSmithyConnection`. pub fn clone_inner(&self) -> CaptureSmithyConnection { self.inner.clone() } + /// Returns the captured connection metadata, if any. pub fn get(&self) -> Option { self.inner.get() } + /// Sets the connection retriever function. pub fn set_connection_retriever(&self, f: F) where F: Fn() -> Option + Send + Sync + 'static, diff --git a/rust-runtime/aws-smithy-runtime/src/client/connectors/test_util.rs b/rust-runtime/aws-smithy-runtime/src/client/connectors/test_util.rs index 457b09888d2e44fe8237397fdef26eb3c8d5b377..c7afd868d4d54440fb78aef5f0a19528767e00c5 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/connectors/test_util.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/connectors/test_util.rs @@ -94,6 +94,11 @@ pub fn capture_request( type ConnectionEvents = Vec; +/// Test data for the [`TestConnector`]. +/// +/// Each `ConnectionEvent` represents one HTTP request and response +/// through the connector. Optionally, a latency value can be set to simulate +/// network latency (done via async sleep in the `TestConnector`). #[derive(Debug)] pub struct ConnectionEvent { latency: Duration, @@ -102,6 +107,7 @@ pub struct ConnectionEvent { } impl ConnectionEvent { + /// Creates a new `ConnectionEvent`. pub fn new(req: HttpRequest, res: HttpResponse) -> Self { Self { res, @@ -116,11 +122,13 @@ impl ConnectionEvent { self } - pub fn req(&self) -> &HttpRequest { + /// Returns the test request. + pub fn request(&self) -> &HttpRequest { &self.req } - pub fn res(&self) -> &HttpResponse { + /// Returns the test response. + pub fn response(&self) -> &HttpResponse { &self.res } } @@ -132,13 +140,13 @@ impl From<(HttpRequest, HttpResponse)> for ConnectionEvent { } #[derive(Debug)] -pub struct ValidateRequest { - pub expected: HttpRequest, - pub actual: HttpRequest, +struct ValidateRequest { + expected: HttpRequest, + actual: HttpRequest, } impl ValidateRequest { - pub fn assert_matches(&self, index: usize, ignore_headers: &[HeaderName]) { + fn assert_matches(&self, index: usize, ignore_headers: &[HeaderName]) { let (actual, expected) = (&self.actual, &self.expected); assert_eq!( actual.uri(), @@ -181,32 +189,41 @@ impl ValidateRequest { } } -/// TestConnection for use as a [`HttpConnector`]. +/// Test connector for use as a [`HttpConnector`]. /// /// A basic test connection. It will: /// - Respond to requests with a preloaded series of responses /// - Record requests for future examination #[derive(Debug, Clone)] -pub struct TestConnection { +pub struct TestConnector { data: Arc>, requests: Arc>>, sleep_impl: SharedAsyncSleep, } -impl TestConnection { +impl TestConnector { + /// Creates a new test connector. pub fn new(mut data: ConnectionEvents, sleep_impl: impl Into) -> Self { data.reverse(); - TestConnection { + TestConnector { data: Arc::new(Mutex::new(data)), requests: Default::default(), sleep_impl: sleep_impl.into(), } } - pub fn requests(&self) -> impl Deref> + '_ { + fn requests(&self) -> impl Deref> + '_ { self.requests.lock().unwrap() } + /// Asserts the expected requests match the actual requests. + /// + /// The expected requests are given as the connection events when the `TestConnector` + /// is created. The `TestConnector` will record the actual requests and assert that + /// they match the expected requests. + /// + /// A list of headers that should be ignored when comparing requests can be passed + /// for cases where headers are non-deterministic or are irrelevant to the test. #[track_caller] pub fn assert_requests_match(&self, ignore_headers: &[HeaderName]) { for (i, req) in self.requests().iter().enumerate() { @@ -222,7 +239,7 @@ impl TestConnection { } } -impl HttpConnector for TestConnection { +impl HttpConnector for TestConnector { fn call(&self, request: HttpRequest) -> BoxFuture { let (res, simulated_latency) = if let Some(event) = self.data.lock().unwrap().pop() { self.requests.lock().unwrap().push(ValidateRequest { diff --git a/rust-runtime/aws-smithy-runtime/src/client/identity.rs b/rust-runtime/aws-smithy-runtime/src/client/identity.rs index a8b8769057f7494e196b6538cbbb760e5be38ce0..7aaef9c3caaac80adfb35004dddd3017a25af25c 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/identity.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/identity.rs @@ -3,4 +3,5 @@ * SPDX-License-Identifier: Apache-2.0 */ +/// Identity resolver implementation for "no auth". pub mod no_auth; diff --git a/rust-runtime/aws-smithy-runtime/src/client/identity/no_auth.rs b/rust-runtime/aws-smithy-runtime/src/client/identity/no_auth.rs index 8814336b3a6929ddada98cecc3765dae9ebc24f7..01121eab9095ff8a04e22c241a1f48c2b495d49e 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/identity/no_auth.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/identity/no_auth.rs @@ -7,19 +7,23 @@ use aws_smithy_runtime_api::client::identity::{Identity, IdentityResolver}; use aws_smithy_runtime_api::client::orchestrator::Future; use aws_smithy_types::config_bag::ConfigBag; +/// Identity for the [`NoAuthScheme`](crate::client::auth::no_auth::NoAuthScheme) auth scheme. #[derive(Debug, Default)] pub struct NoAuthIdentity; impl NoAuthIdentity { + /// Creates a new `NoAuthIdentity`. pub fn new() -> Self { Self } } +/// Identity resolver for the [`NoAuthScheme`](crate::client::auth::no_auth::NoAuthScheme) auth scheme. #[derive(Debug, Default)] pub struct NoAuthIdentityResolver; impl NoAuthIdentityResolver { + /// Creates a new `NoAuthIdentityResolver`. pub fn new() -> Self { Self } diff --git a/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs b/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs index a6a73c2875d5348f9f44cbc1659d1532ff1591dc..c9dd0746059d689c1f37d595fb88fcdc5460a932 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/interceptors.rs @@ -280,6 +280,7 @@ impl ConditionallyEnabledInterceptor { } } +/// Interceptor that maps the request with a given function. pub struct MapRequestInterceptor { f: F, _phantom: PhantomData, @@ -292,6 +293,7 @@ impl fmt::Debug for MapRequestInterceptor { } impl MapRequestInterceptor { + /// Creates a new `MapRequestInterceptor`. pub fn new(f: F) -> Self { Self { f, @@ -324,6 +326,7 @@ where } } +/// Interceptor that mutates the request with a given function. pub struct MutateRequestInterceptor { f: F, } @@ -335,6 +338,7 @@ impl fmt::Debug for MutateRequestInterceptor { } impl MutateRequestInterceptor { + /// Creates a new `MutateRequestInterceptor`. pub fn new(f: F) -> Self { Self { f } } diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs index 404ffdae5af4cad1c2781db8a2028b971d61f0b0..b86953dded2e31485ed3ea186ab73fc5b33936d1 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs @@ -37,7 +37,6 @@ mod auth; /// Defines types that implement a trait for endpoint resolution pub mod endpoints; mod http; -pub mod interceptors; macro_rules! halt { ([$ctx:ident] => $err:expr) => {{ @@ -83,6 +82,15 @@ macro_rules! run_interceptors { }; } +/// Orchestrates the execution of a request and handling of a response. +/// +/// The given `runtime_plugins` will be used to generate a `ConfigBag` for this request, +/// and then the given `input` will be serialized and transmitted. When a response is +/// received, it will be deserialized and returned. +/// +/// This orchestration handles retries, endpoint resolution, identity resolution, and signing. +/// Each of these are configurable via the config and runtime components given by the runtime +/// plugins. pub async fn invoke( service_name: &str, operation_name: &str, @@ -111,6 +119,12 @@ pub enum StopPoint { BeforeTransmit, } +/// Same as [`invoke`], but allows for returning early at different points during orchestration. +/// +/// Orchestration will cease at the point specified by `stop_point`. This is useful for orchestrations +/// that don't need to actually transmit requests, such as for generating presigned requests. +/// +/// See the docs on [`invoke`] for more details. pub async fn invoke_with_stop_point( service_name: &str, operation_name: &str, diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/endpoints.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/endpoints.rs index 4f170ec64174d5764c73aa89af0e61766e3325d0..76ce7f4037442bda1ae92b11f20e48ca4c65afe5 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/endpoints.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/endpoints.rs @@ -21,12 +21,14 @@ use std::fmt::Debug; use std::str::FromStr; use tracing::trace; -#[derive(Debug, Clone)] +/// An endpoint resolver that uses a static URI. +#[derive(Clone, Debug)] pub struct StaticUriEndpointResolver { endpoint: Uri, } impl StaticUriEndpointResolver { + /// Create a resolver that resolves to `http://localhost:{port}`. pub fn http_localhost(port: u16) -> Self { Self { endpoint: Uri::from_str(&format!("http://localhost:{port}")) @@ -34,6 +36,7 @@ impl StaticUriEndpointResolver { } } + /// Create a resolver that resolves to the given URI. pub fn uri(endpoint: Uri) -> Self { Self { endpoint } } @@ -64,7 +67,13 @@ impl From for EndpointResolverParams { } } -#[derive(Debug, Clone)] +/// Default implementation of [`EndpointResolver`]. +/// +/// This default endpoint resolver implements the `EndpointResolver` trait by +/// converting the type-erased [`EndpointResolverParams`] into the concrete +/// endpoint params for the service. It then delegates endpoint resolution +/// to an underlying resolver that is aware of the concrete type. +#[derive(Clone, Debug)] pub struct DefaultEndpointResolver { inner: SharedEndpointResolver, } @@ -77,6 +86,7 @@ where } impl DefaultEndpointResolver { + /// Creates a new `DefaultEndpointResolver`. pub fn new(resolve_endpoint: SharedEndpointResolver) -> Self { Self { inner: resolve_endpoint, diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors.rs deleted file mode 100644 index b9de2daa37bde2de6c7489ee5f0be7c461d03ba3..0000000000000000000000000000000000000000 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -mod service_clock_skew; - -pub use service_clock_skew::{ServiceClockSkew, ServiceClockSkewInterceptor}; diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries.rs b/rust-runtime/aws-smithy-runtime/src/client/retries.rs index 893c5f0163e7c2c4f84eaf0aa54e3ec5b1b6189d..8ea71ebb5ed29eb7dde786f7bb9f1ce656d7a4d5 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries.rs @@ -3,15 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +/// Smithy retry classifiers. pub mod classifier; + +/// Smithy retry strategies. pub mod strategy; mod client_rate_limiter; mod token_bucket; use aws_smithy_types::config_bag::{Storable, StoreReplace}; -pub use client_rate_limiter::{ClientRateLimiter, ClientRateLimiterRuntimePlugin}; use std::fmt; + +pub use client_rate_limiter::{ClientRateLimiter, ClientRateLimiterRuntimePlugin}; pub use token_bucket::{TokenBucket, TokenBucketRuntimePlugin}; #[doc(hidden)] diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/classifier.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/classifier.rs index f22c76513666c638e13a8eb67d3d6894fa3cad9c..254cb636d5ae46cae0afe5976dc6e0817e26e7f9 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/classifier.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/classifier.rs @@ -50,6 +50,7 @@ where } } +/// Classifies response, timeout, and connector errors as retryable or not. #[derive(Debug, Default)] pub struct SmithyErrorClassifier { _inner: PhantomData, diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/client_rate_limiter.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/client_rate_limiter.rs index 5453cad2718330c52b3f5f5abb7442a93324afe2..661f0f854c2abf97aa0333be6ef7d151ec5f6e91 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/client_rate_limiter.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/client_rate_limiter.rs @@ -16,7 +16,7 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use tracing::debug; -/// A [RuntimePlugin] to provide a client rate limiter, usable by a retry strategy. +/// A [`RuntimePlugin`] to provide a client rate limiter, usable by a retry strategy. #[non_exhaustive] #[derive(Debug)] pub struct ClientRateLimiterRuntimePlugin { @@ -24,6 +24,7 @@ pub struct ClientRateLimiterRuntimePlugin { } impl ClientRateLimiterRuntimePlugin { + /// Create a new [`ClientRateLimiterRuntimePlugin`]. pub fn new(seconds_since_unix_epoch: f64) -> Self { Self { rate_limiter: ClientRateLimiter::new(seconds_since_unix_epoch), @@ -65,6 +66,7 @@ const BETA: f64 = 0.7; /// Controls how aggressively we scale up after being throttled const SCALE_CONSTANT: f64 = 0.4; +/// Rate limiter for adaptive retry. #[derive(Clone, Debug)] pub struct ClientRateLimiter { inner: Arc>, @@ -107,6 +109,7 @@ impl Storable for ClientRateLimiter { } impl ClientRateLimiter { + /// Creates a new [`ClientRateLimiter`]. pub fn new(seconds_since_unix_epoch: f64) -> Self { Self::builder() .tokens_retrieved_per_second(MIN_FILL_RATE) diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy.rs index c046a4d9f715089b59f1ee18c234db492147d14b..c441aa4816e74f839fb7798c6f9db8a5c9cf85fa 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy.rs @@ -3,12 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#[cfg(feature = "test-util")] -mod fixed_delay; mod never; pub(crate) mod standard; -#[cfg(feature = "test-util")] -pub use fixed_delay::FixedDelayRetryStrategy; pub use never::NeverRetryStrategy; pub use standard::StandardRetryStrategy; + +#[cfg(feature = "test-util")] +mod fixed_delay; +#[cfg(feature = "test-util")] +pub use fixed_delay::FixedDelayRetryStrategy; diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/fixed_delay.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/fixed_delay.rs index c6315512a3c2ae32b4873b52113e2db526982621..886b7a61b225f9230e7a2643a8c791c174dbf68e 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/fixed_delay.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/fixed_delay.rs @@ -12,8 +12,8 @@ use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_types::config_bag::ConfigBag; use std::time::Duration; -// A retry policy used in tests. This relies on an error classifier already present in the config bag. -// If a server response is retryable, it will be retried after a fixed delay. +/// A retry policy used in tests. This relies on an error classifier already present in the config bag. +/// If a server response is retryable, it will be retried after a fixed delay. #[derive(Debug, Clone)] pub struct FixedDelayRetryStrategy { fixed_delay: Duration, @@ -21,6 +21,7 @@ pub struct FixedDelayRetryStrategy { } impl FixedDelayRetryStrategy { + /// Create a new retry policy with a fixed delay. pub fn new(fixed_delay: Duration) -> Self { Self { fixed_delay, @@ -28,6 +29,7 @@ impl FixedDelayRetryStrategy { } } + /// Create a new retry policy with a one second delay. pub fn one_second_delay() -> Self { Self::new(Duration::from_secs(1)) } diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/never.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/never.rs index b59b8fb7f167928583c33d425031b79143adb0b9..7baf4a14265d664f8dc6aea65f6629b1dfd09c24 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/never.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/never.rs @@ -9,11 +9,13 @@ use aws_smithy_runtime_api::client::retries::{RetryStrategy, ShouldAttempt}; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_types::config_bag::ConfigBag; +/// A retry strategy that never retries. #[non_exhaustive] #[derive(Debug, Clone, Default)] -pub struct NeverRetryStrategy {} +pub struct NeverRetryStrategy; impl NeverRetryStrategy { + /// Creates a new `NeverRetryStrategy`. pub fn new() -> Self { Self::default() } diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/standard.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/standard.rs index 915f8fad0f9b4f58a2983b43dbcd39b8835d80f5..ee32a6a63da4dd15b24bffc9299e394bf556a260 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/standard.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/strategy/standard.rs @@ -24,6 +24,7 @@ use tracing::debug; // The initial attempt, plus three retries. const DEFAULT_MAX_ATTEMPTS: u32 = 4; +/// Retry strategy with exponential backoff, max attempts, and a token bucket. #[derive(Debug)] pub struct StandardRetryStrategy { // Retry settings @@ -39,13 +40,13 @@ impl Storable for StandardRetryStrategy { } impl StandardRetryStrategy { + /// Create a new standard retry strategy with the given config. pub fn new(retry_config: &RetryConfig) -> Self { let base = if retry_config.use_static_exponential_base() { || 1.0 } else { fastrand::f64 }; - // TODO(enableNewSmithyRuntimeLaunch) add support for `retry_config.reconnect_mode()` here or in the orchestrator flow. Self::default() .with_base(base) .with_max_backoff(retry_config.max_backoff()) @@ -53,21 +54,25 @@ impl StandardRetryStrategy { .with_initial_backoff(retry_config.initial_backoff()) } + /// Changes the exponential backoff base. pub fn with_base(mut self, base: fn() -> f64) -> Self { self.base = base; self } + /// Changes the max number of attempts. pub fn with_max_attempts(mut self, max_attempts: u32) -> Self { self.max_attempts = max_attempts; self } + /// Changes the initial backoff time. pub fn with_initial_backoff(mut self, initial_backoff: Duration) -> Self { self.initial_backoff = initial_backoff; self } + /// Changes the maximum backoff time. pub fn with_max_backoff(mut self, max_backoff: Duration) -> Self { self.max_backoff = max_backoff; self diff --git a/rust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rs b/rust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rs index a7c95d2a51139ecff764c8b57a0d079046342068..686185b1d1a7676562eb4cb651820bc516ac2d48 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/retries/token_bucket.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use tokio::sync::{OwnedSemaphorePermit, Semaphore}; use tracing::trace; -/// A [RuntimePlugin] to provide a token bucket, usable by a retry strategy. +/// A [`RuntimePlugin`] to provide a token bucket, usable by a retry strategy. #[non_exhaustive] #[derive(Debug, Default)] pub struct TokenBucketRuntimePlugin { @@ -19,6 +19,7 @@ pub struct TokenBucketRuntimePlugin { } impl TokenBucketRuntimePlugin { + /// Creates a new `TokenBucketRuntimePlugin` with the given initial quota. pub fn new(initial_tokens: usize) -> Self { Self { token_bucket: TokenBucket::new(initial_tokens), @@ -53,6 +54,7 @@ const RETRY_COST: u32 = 5; const RETRY_TIMEOUT_COST: u32 = RETRY_COST * 2; const PERMIT_REGENERATION_AMOUNT: usize = 1; +/// Token bucket used for standard and adaptive retry. #[derive(Clone, Debug)] pub struct TokenBucket { semaphore: Arc, @@ -77,6 +79,7 @@ impl Default for TokenBucket { } impl TokenBucket { + /// Creates a new `TokenBucket` with the given initial quota. pub fn new(initial_quota: usize) -> Self { Self { semaphore: Arc::new(Semaphore::new(initial_quota)), diff --git a/rust-runtime/aws-smithy-runtime/src/client/test_util.rs b/rust-runtime/aws-smithy-runtime/src/client/test_util.rs index 30adb4f6cb60a59563fc15808de5679031c6582b..1173adc3db6313c2650c25c7a093d45e8f64b2ba 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/test_util.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/test_util.rs @@ -3,5 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +/// Test response deserializer implementations. pub mod deserializer; + +/// Test request serializer implementations. pub mod serializer; diff --git a/rust-runtime/aws-smithy-runtime/src/client/test_util/deserializer.rs b/rust-runtime/aws-smithy-runtime/src/client/test_util/deserializer.rs index 4b1d43ae793cb92797ee98fe45ccd31396dbbe80..4e83052d43ce6f9505540d57f28d846ff7f5087f 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/test_util/deserializer.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/test_util/deserializer.rs @@ -10,19 +10,21 @@ use aws_smithy_runtime_api::client::ser_de::{ResponseDeserializer, SharedRespons use aws_smithy_types::config_bag::{FrozenLayer, Layer}; use std::sync::Mutex; +/// Test response deserializer that always returns the same canned response. #[derive(Default, Debug)] pub struct CannedResponseDeserializer { inner: Mutex>>>, } impl CannedResponseDeserializer { + /// Creates a new `CannedResponseDeserializer` with the given canned response. pub fn new(output: Result>) -> Self { Self { inner: Mutex::new(Some(output)), } } - pub fn take(&self) -> Option>> { + fn take(&self) -> Option>> { match self.inner.lock() { Ok(mut guard) => guard.take(), Err(_) => None, diff --git a/rust-runtime/aws-smithy-runtime/src/client/test_util/serializer.rs b/rust-runtime/aws-smithy-runtime/src/client/test_util/serializer.rs index ec3eb2dafd5b2e8a6d693643a5edeb07a29cfee2..573eea52935a4e614b84ed8eba1e0f4ab9e1ef8b 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/test_util/serializer.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/test_util/serializer.rs @@ -11,25 +11,28 @@ use aws_smithy_runtime_api::client::ser_de::{RequestSerializer, SharedRequestSer use aws_smithy_types::config_bag::{ConfigBag, FrozenLayer, Layer}; use std::sync::Mutex; +/// Test [`RequestSerializer`] that returns a canned request. #[derive(Default, Debug)] pub struct CannedRequestSerializer { inner: Mutex>>, } impl CannedRequestSerializer { + /// Create a new [`CannedRequestSerializer`] with a successful canned request. pub fn success(request: HttpRequest) -> Self { Self { inner: Mutex::new(Some(Ok(request))), } } + /// Create a new [`CannedRequestSerializer`] with a canned error. pub fn failure(error: BoxError) -> Self { Self { inner: Mutex::new(Some(Err(error))), } } - pub fn take(&self) -> Option> { + fn take(&self) -> Option> { match self.inner.lock() { Ok(mut guard) => guard.take(), Err(_) => None, diff --git a/rust-runtime/aws-smithy-runtime/src/lib.rs b/rust-runtime/aws-smithy-runtime/src/lib.rs index 3afb476bf9df3c3e4c149f7ee800c8cbbc214c6f..b40610a77ccde9678c2bf2904a42ce85cbe136cd 100644 --- a/rust-runtime/aws-smithy-runtime/src/lib.rs +++ b/rust-runtime/aws-smithy-runtime/src/lib.rs @@ -12,7 +12,7 @@ //! - `test-util`: Enables utilities for unit tests. DO NOT ENABLE IN PRODUCTION. #![warn( - // missing_docs, + missing_docs, rustdoc::missing_crate_level_docs, unreachable_pub, rust_2018_idioms @@ -22,6 +22,7 @@ #[cfg(feature = "client")] pub mod client; +/// A data structure for persisting and sharing state between multiple clients. pub mod static_partition_map; /// General testing utilities. diff --git a/rust-runtime/aws-smithy-runtime/src/static_partition_map.rs b/rust-runtime/aws-smithy-runtime/src/static_partition_map.rs index 10b0070ccfa2239600bcaf857f74885dec5791eb..2f70869f35591d1c03e6f841740d49e54e35abb9 100644 --- a/rust-runtime/aws-smithy-runtime/src/static_partition_map.rs +++ b/rust-runtime/aws-smithy-runtime/src/static_partition_map.rs @@ -77,6 +77,7 @@ pub struct StaticPartitionMap { } impl StaticPartitionMap { + /// Creates a new `StaticPartitionMap`. pub const fn new() -> Self { Self { inner: OnceCell::new(), @@ -102,18 +103,20 @@ where K: Eq + Hash, V: Clone, { + /// Gets the value for the given partition key. #[must_use] pub fn get(&self, partition_key: K) -> Option { self.get_or_init_inner().get(&partition_key).cloned() } + /// Gets the value for the given partition key, initializing it with `init` if it doesn't exist. #[must_use] - pub fn get_or_init(&self, partition_key: K, f: F) -> V + pub fn get_or_init(&self, partition_key: K, init: F) -> V where F: FnOnce() -> V, { let mut inner = self.get_or_init_inner(); - let v = inner.entry(partition_key).or_insert_with(f); + let v = inner.entry(partition_key).or_insert_with(init); v.clone() } } @@ -123,6 +126,7 @@ where K: Eq + Hash, V: Clone + Default, { + /// Gets the value for the given partition key, initializing it if it doesn't exist. #[must_use] pub fn get_or_init_default(&self, partition_key: K) -> V { self.get_or_init(partition_key, V::default) diff --git a/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs b/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs index a25c97c42f852e8fb5e6b7b3049144dbe8f97506..85730d00bc585c54faccf1ef4f44fefcd2877f20 100644 --- a/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs +++ b/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs @@ -10,12 +10,6 @@ use tracing::subscriber::DefaultGuard; use tracing::Level; use tracing_subscriber::fmt::TestWriter; -struct Tee { - buf: Arc>>, - quiet: bool, - inner: W, -} - /// A guard that resets log capturing upon being dropped. #[derive(Debug)] pub struct LogCaptureGuard(DefaultGuard); @@ -44,13 +38,24 @@ pub fn capture_test_logs() -> (LogCaptureGuard, Rx) { (LogCaptureGuard(guard), rx) } +/// Receiver for the captured logs. pub struct Rx(Arc>>); impl Rx { + /// Returns the captured logs as a string. + /// + /// # Panics + /// This will panic if the logs are not valid UTF-8. pub fn contents(&self) -> String { String::from_utf8(self.0.lock().unwrap().clone()).unwrap() } } +struct Tee { + buf: Arc>>, + quiet: bool, + inner: W, +} + impl Tee { fn stdout() -> (Self, Rx) { let buf: Arc>> = Default::default();