Repository navigation
feat(http3): route requests through the HTTP/3 client scheduler - #15
Merged
Merged
Conversation
takeokunn
force-pushed
the
p6-http3-native-client
branch
from
October 25, 2026 04:20
15402f7 to
ab28025
Compare
takeokunn
force-pushed
the
p6-http3-native-client
branch
8 times, most recently
from
October 26, 2026 11:27
6ab6b8f to
5d0e0e6
Compare
Set the cl-quic-kit input to revision 8e85e63bf601ff5b004f15fe36818fba125663eb and follow the root cl-tls-kit and cl-crypto-kit inputs.
takeokunn
force-pushed
the
p6-http3-native-client
branch
from
October 26, 2026 15:54
5d0e0e6 to
61e5c09
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relation to the HTTP/2 scheduler in PR #13
PR #13 adds an HTTP/2 connection mutex around stream setup and elects one caller to pump inbound frames. The native HTTP/3 scheduler uses a single-owner pump as well: the first request caller becomes the owner, and other callers enqueue and wait. QUIC assigns HTTP/3 stream IDs, so this scheduler does not reserve stream IDs under the HTTP/2 connection mutex.
The owner runs the connection loop synchronously until its request is complete and both the pending queue and active-stream table are empty. It opens pending streams, polls QUIC, services critical control and QPACK streams, and advances active request streams round-robin while respecting pending writes. Body and response callbacks run inline on the owner. A request submitted reentrantly from a callback is rejected.
The owner loop serializes scheduler-owned request QPACK preparation, HEADERS writing, and encoder commit.
make-http3-client's:serializecallback defaults to invoking its thunk directly without a lock. Callers that mutate public QPACK state concurrently outside the owner loop must supply a:serializecallback that provides their synchronization.Native scheduler callbacks and close behavior
Native scheduler operation requires
poll-function,try-read-stream, andstream-write-pending-ptogether.try-write-streamis optional: when present, the scheduler uses it to submit request frames without waiting; when absent, it falls back towrite-stream. Other synchronous operations continue to usewrite-stream.close-http3-clientcloses HTTP/3 streams and stops the HTTP/3 scheduler, but leaves the underlying QUIC connection open.close-http3-quic-adaptercloses HTTP/3 streams and then closes QUIC. Both return true after successful or already-completed close; a reentrant close by the close owner returns nil. If both HTTP/3 cleanup and QUIC close fail,close-http3-quic-adapterraises the HTTP/3 cleanup error and warns about the QUIC error. If only HTTP/3 cleanup fails and QUIC close succeeds, it raises the cleanup error. If only QUIC close fails, it raises the QUIC error.Dependency pins
The root pins
cl-crypto-kitat761e9592as a flake input so the updatedcl-quic-kitinput can follow the root crypto dependency. Thecl-quic-kitpin advances to46bfeaccfor its publicclient-receive-frames(client, level, packet-number, frames)API, which lets tests supply frame batches at a selected packet number.Scheduler test coverage
Scheduler tests exercise concurrent progress while one request streams a large upload; ownership handoff after the owner caller's deadline, unwind, interruption, and request error; QPACK-blocked request resumption; close waking all waiters with one condition; QUIC close failure preservation; and discovery of peer control and QPACK streams that arrive after setup. The late-stream test uses the optional
accept-peer-unidirectional-streamcallback supplied tomake-http3-client.Protocol-boundary tests verify that a response stream is not read while its QPACK section is blocked, duplicate control streams close QUIC while request-stream errors remain isolated, peer stream-count and prefix-byte limits apply before retention, and the public scheduler emits the dynamic-QPACK field section and encoder instructions.
The response-preservation test injects STOP_SENDING(H3_NO_ERROR) during a streaming request and verifies that the complete response is returned and further request writes stop.
Scheduler portability
The scheduler mutex and condition variable are available only under SBCL. Non-SBCL builds use no-op lock and wait wrappers, so concurrent callers are not serialized there. Scheduler concurrency tests use SBCL threads.