From 344b3031e9f6716ac8ac10b96565b174030d5349 Mon Sep 17 00:00:00 2001 From: ZheFox <77232781+zhefox@users.noreply.github.com> Date: Fri, 4 Sep 2026 18:59:52 +0800 Subject: [PATCH] test(integration): stabilize truncated h2c stream ordering --- .../integration/src/bin/mock_openai_upstream.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/aether-testing/integration/src/bin/mock_openai_upstream.rs b/crates/aether-testing/integration/src/bin/mock_openai_upstream.rs index 58c297519..8dacebdb2 100644 --- a/crates/aether-testing/integration/src/bin/mock_openai_upstream.rs +++ b/crates/aether-testing/integration/src/bin/mock_openai_upstream.rs @@ -37,6 +37,7 @@ const MAX_MOCK_REQUEST_BODY_BYTES: usize = 1024 * 1024; const BASIS_POINTS: u16 = 10_000; const DEFAULT_TIMEOUT_HOLD_MS: u64 = 60_000; const REQUEST_SEQUENCE_HEADER: &str = "x-mock-request-sequence"; +const TRUNCATED_STREAM_FLUSH_DELAY: Duration = Duration::from_millis(10); const RANDOM_DOMAIN_FAULT: u64 = 0x5c32_22f7_27d4_7a6f; const RANDOM_DOMAIN_FIRST_BYTE: u64 = 0x087d_89d9_3bc3_15db; @@ -646,8 +647,10 @@ fn build_chat_sse_response( if profile.truncate_after_chunks == Some(0) || profile.truncate_after_chunks == Some(index + 1) { - // Force Hyper to flush the successful frame before observing the body error. - tokio::task::yield_now().await; + // Hyper translates body errors into RST_STREAM for HTTP/2. Keep the body + // pending briefly so the response headers and successful DATA frame are + // written before Hyper observes the error. + tokio::time::sleep(TRUNCATED_STREAM_FLUSH_DELAY).await; record_fault(&app, Fault::TruncateStream); yield Err::(truncated_stream_error()); return; @@ -701,8 +704,10 @@ fn build_responses_sse_response( if profile.truncate_after_chunks == Some(0) || profile.truncate_after_chunks == Some(index + 1) { - // Force Hyper to flush the successful frame before observing the body error. - tokio::task::yield_now().await; + // Hyper translates body errors into RST_STREAM for HTTP/2. Keep the body + // pending briefly so the response headers and successful DATA frame are + // written before Hyper observes the error. + tokio::time::sleep(TRUNCATED_STREAM_FLUSH_DELAY).await; record_fault(&app, Fault::TruncateStream); yield Err::(truncated_stream_error()); return;