-
Notifications
You must be signed in to change notification settings - Fork 266
Description
Describe the bug
Using the example from https://github.com/awslabs/aws-sdk-rust/blob/main/sdk/aws-smithy-http-client/src/test_util/dvr/record.rs but with dynamodb client (for instance just a list tables command) makes the recording hang. It works for S3, but not for DynamoDB. After the request times out and all recorded events are dumped to a file, the file contains only the request event.
Regression Issue
- Select this option if this issue appears to be a regression.
Expected Behavior
I expect the request to succeed, and the request and response events should be present in the dump file.
Current Behavior
The request never completes when using the recording client.
Reproduction Steps
Run the following rust code:
main.rs
use aws_config::{BehaviorVersion, Region};
use aws_smithy_async::rt::sleep::default_async_sleep;
use aws_smithy_http_client::test_util::dvr::RecordingClient;
use aws_smithy_runtime::client::http::hyper_014::default_connector;
use aws_smithy_runtime_api::client::http::HttpConnectorSettingsBuilder;
#[tokio::main]
async fn main() {
let settings = HttpConnectorSettingsBuilder::default().build();
let http_client = default_connector(&settings, default_async_sleep()).unwrap();
let http_client = RecordingClient::new(http_client);
let config = aws_config::load_defaults(BehaviorVersion::latest()).await;
let ddb_config = aws_sdk_dynamodb::Config::from(&config)
.to_builder()
.http_client(http_client.clone())
.region(Region::new("eu-west-1"))
.build();
let ddb_client = aws_sdk_dynamodb::Client::from_conf(ddb_config);
let response = ddb_client.list_tables().send().await.unwrap();
println!("Response: {:#?}", response);
http_client.dump_to_file("recording.json").unwrap();
}
cargo.toml
[package]
name = "recorder-test"
version = "0.1.0"
edition = "2024"
[dependencies]
aws-config = "1.8.0"
aws-sdk-dynamodb = "1.80.0"
aws-smithy-async = "1.2.5"
aws-smithy-http-client = { version = "1.0.5", features = ["test-util"] }
aws-smithy-runtime = { version = "1.8.3" }
aws-smithy-runtime-api = "1.8.1"
tokio = { version = "1.45.1", features = ["macros", "rt-multi-thread"] }
Possible Solution
It seems to be related to the complex task and channel handling in the recorder. If we clone the request body, it seems to work as expected.
diff --git a/sdk/aws-smithy-http-client/src/test_util/dvr/record.rs b/sdk/aws-smithy-http-client/src/test_util/dvr/record.rs
index 51759dfeba3..d7f900dfac0 100644
--- a/sdk/aws-smithy-http-client/src/test_util/dvr/record.rs
+++ b/sdk/aws-smithy-http-client/src/test_util/dvr/record.rs
@@ -131,8 +131,16 @@ fn record_body(
direction: Direction,
event_bus: Arc<Mutex<Vec<Event>>>,
) -> JoinHandle<()> {
- let (sender, output_body) = crate::test_util::body::channel_body();
- let real_body = std::mem::replace(body, output_body);
+ // For cloneable bodies (like small JSON payloads), record from a clone
+ // to avoid disrupting HTTP semantics. This fixes issues with services
+ // like DynamoDB that are sensitive to body handling.
+ let (real_body, sender) = if let Some(cloned_body) = body.try_clone() {
+ (cloned_body, None)
+ } else {
+ let (sender, output_body) = crate::test_util::body::channel_body();
+ (std::mem::replace(body, output_body), Some(sender))
+ };
+
tokio::spawn(async move {
let mut real_body = real_body;
let mut sender = sender;
@@ -147,18 +155,22 @@ fn record_body(
direction,
},
});
- // This happens if the real connection is closed during recording.
- // Need to think more carefully if this is the correct thing to log in this
- // case.
- if sender.send_data(data).await.is_err() {
- event_bus.lock().unwrap().push(Event {
- connection_id: event_id,
- action: Action::Eof {
- direction: direction.opposite(),
- ok: false,
- },
- })
- };
+
+ if let Some(ref mut sender) = sender {
+ // This happens if the real connection is closed during recording.
+ // Need to think more carefully if this is the correct thing to log in this
+ // case.
+ if sender.send_data(data).await.is_err() {
+ event_bus.lock().unwrap().push(Event {
+ connection_id: event_id,
+ action: Action::Eof {
+ direction: direction.opposite(),
+ ok: false,
+ },
+ });
+ break;
+ }
+ }
}
None => {
event_bus.lock().unwrap().push(Event {
@@ -168,7 +180,9 @@ fn record_body(
direction,
},
});
- drop(sender);
+ if let Some(sender) = sender {
+ drop(sender);
+ }
break;
}
Some(Err(_err)) => {
@@ -179,7 +193,9 @@ fn record_body(
direction,
},
});
- sender.abort();
+ if let Some(sender) = sender {
+ sender.abort();
+ }
break;
}
}
Additional Information/Context
No response
Version
aws-config = "1.8.0"
aws-sdk-dynamodb = "1.80.0"
aws-smithy-async = "1.2.5"
aws-smithy-http-client = { version = "1.0.5", features = ["test-util"] }
aws-smithy-runtime = { version = "1.8.3" }
aws-smithy-runtime-api = "1.8.1"
Environment details (OS name and version, etc.)
MacOS Sonoma 14.6.1, Apple M2 Pro
Logs
No response