From ac0d6f06a97e514e17a1b32de9dc2981b0afce8d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 7 May 2026 14:24:52 +0000 Subject: [PATCH] fix(quic-interop): detect multiplexing by URL count, not TESTCASE name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The smoking gun from the 2026-05-07 multiplex run boot log: [boot] DEBUG=1; ...; TESTCASE=transfer; ROLE=client [boot] transfer mode: parallel=false urls=1999 quic-interop-runner sets TESTCASE_CLIENT=transfer for ALL the transfer-family testcases (transfer, multiplexing, transferloss, transfercorruption). Discrimination between transfer (1 file) and multiplexing (~2000 files) happens by URL count, NOT by TESTCASE name — so our check `parallel = (testcase == "multiplexing")` was always false, even for the multiplexing test, and we always took the serial fallback path: client.get(authority, path) per URL, opening one stream + awaiting before the next. That's why the wire showed exactly one stream per RTT for the entire 60s. Fix: parallel = (token count of REQUESTS env var) > 1. Effectively: - 1 URL → transfer testcase, serial path - >1 URL → multiplexing testcase, batched-parallel path Verified the writer's batched coalescing already works in unit tests (MultiplexingCoalescingTest, MultiplexingAioquicTpsTest both green at ~9 streams/packet). With this dispatch fix, the live runner should finally reach the batched code path. Bumped WRITER_DEBUG_BUILD_ID so the next [boot] line confirms the fix is deployed. --- .../quic/interop/runner/InteropClient.kt | 16 +++++++++++++++- .../vitorpamplona/quic/connection/WriterDebug.kt | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/quic/interop/src/main/kotlin/com/vitorpamplona/quic/interop/runner/InteropClient.kt b/quic/interop/src/main/kotlin/com/vitorpamplona/quic/interop/runner/InteropClient.kt index fe8a68137..12ed601d6 100644 --- a/quic/interop/src/main/kotlin/com/vitorpamplona/quic/interop/runner/InteropClient.kt +++ b/quic/interop/src/main/kotlin/com/vitorpamplona/quic/interop/runner/InteropClient.kt @@ -198,7 +198,21 @@ fun main() { initialVersion = initialVersion, keyLogPath = keyLogPath, qlogDir = qlogDir, - parallel = (testcase == "multiplexing"), + // The runner reuses TESTCASE_CLIENT=transfer for the + // multiplexing testcase — discrimination is by URL + // count, not testcase name. We were checking + // testcase == "multiplexing" which is NEVER true + // (we'd see TESTCASE=multiplexing only on a + // hypothetical client where the runner explicitly + // sets it). Symptom: 60s timeout with 1421/2000 + // files at 1 stream / RTT — exactly the serial + // client.get(...) path. Confirmed via the boot log: + // [boot] TESTCASE=transfer; transfer mode: + // parallel=false urls=1999 + // + // Cheap whitespace tokenization here just counts; + // runTransferTest re-parses into URI[] inside. + parallel = requests.split(Regex("\\s+")).count { it.isNotBlank() } > 1, ) } diff --git a/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/WriterDebug.kt b/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/WriterDebug.kt index 0fbd586f2..7b5d0facf 100644 --- a/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/WriterDebug.kt +++ b/quic/src/commonMain/kotlin/com/vitorpamplona/quic/connection/WriterDebug.kt @@ -39,4 +39,4 @@ var writerDebugEnabled: Boolean = false * docker layer cache didn't serve a stale jar). Bump when adding new * trace lines to make them traceable from the wire run. */ -const val WRITER_DEBUG_BUILD_ID: String = "2026-05-07-parallel-branch-v1" +const val WRITER_DEBUG_BUILD_ID: String = "2026-05-07-fix-parallel-detection-v1"