Skip to content

quic: apply multiple fixes to flow control signaling - #65309

Open
jasnell wants to merge 1 commit into
nodejs:mainfrom
jasnell:jasnell/quic-flow-control-fixes
Open

quic: apply multiple fixes to flow control signaling#65309
jasnell wants to merge 1 commit into
nodejs:mainfrom
jasnell:jasnell/quic-flow-control-fixes

Conversation

@jasnell

@jasnell jasnell commented Aug 15, 2026

Copy link
Copy Markdown
Member

Fixing up the QUIC flow control signaling and closed stream handling, expand tests.

Update the flow control handling after the iter streams byte-budget based flow control updates.

@nodejs/quic @pimterry @martenrichter

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/quic

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Aug 15, 2026
@nodejs-github-bot

This comment was marked as outdated.

@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 44.18605% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.31%. Comparing base (2929417) to head (e3c1b86).
⚠️ Report is 14 commits behind head on main.

Files with missing lines Patch % Lines
src/dataqueue/queue.cc 0.00% 13 Missing and 1 partial ⚠️
lib/internal/blob.js 65.51% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #65309      +/-   ##
==========================================
- Coverage   90.34%   90.31%   -0.04%     
==========================================
  Files         751      751              
  Lines      250330   250510     +180     
  Branches    47321    47350      +29     
==========================================
+ Hits       226171   226243      +72     
- Misses      15557    15619      +62     
- Partials     8602     8648      +46     
Files with missing lines Coverage Δ
lib/internal/blob.js 87.75% <65.51%> (-2.11%) ⬇️
src/dataqueue/queue.cc 66.04% <0.00%> (-1.53%) ⬇️

... and 41 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Comment thread src/dataqueue/queue.cc
backpressure_listeners_.begin(), backpressure_listeners_.end());
for (auto* listener : listeners) {
if (backpressure_listeners_.contains(listener)) {
listener->EntryRead(amount);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it is guaranteed that the DataQueueImpl object is still not destroyed after exiting from EntryRead ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this was also a point for the older code..

Comment thread src/dataqueue/queue.cc
backpressure_listeners_.begin(), backpressure_listeners_.end());
for (auto* listener : listeners) {
if (backpressure_listeners_.contains(listener)) {
listener->BeforePull();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Comment thread src/quic/streams.cc
if (session().is_destroyed()) return;
Session::SendPendingDataScope send_scope(&session());
session().Consume(id(), amount);
uncredited_bytes_ -= std::min<uint64_t>(uncredited_bytes_, amount);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I do not understand this.
If the amount is zero, then uncreduted_bytes_ will be set to zero. Is this the intended behavior?

Comment thread src/quic/streams.cc
// This is the only place we notify — not on every ReceiveData call —
// so the reader only wakes up when there is a well-sized entry to
// consume.
if (reader_) reader_->NotifyPull();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if only tiny data packets arrive, maybe with a temporal distance of a second? Would this lead to stalls?

Comment thread src/quic/streams.cc
// it past the final size) so the bytes have been dropped. They will
// never reach a reader, which means EntryRead() will never fire for
// them -- return their flow control credit here instead of leaking it.
uncredited_bytes_ -= std::min<uint64_t>(uncredited_bytes_, flushed);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above?

Comment thread src/quic/streams.h
// Number of received bytes that are still holding inbound flow control
// credit -- that is, bytes that ngtcp2 has delivered to us but that have
// not yet been handed to the JavaScript consumer (they are sitting in
// recv_accumulator_ or in the inbound_ DataQueue). This is incremented

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be it can also be in nghttp3, so it does not hold data?

},
maxStreamWindow: kStreamWindow,
maxWindow: kConnWindow,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test h3 or pure quic. As h3 is the default.

initialMaxStreamDataBidiRemote: kStreamWindow,
initialMaxData: kConnWindow,
// Allow all streams to be open at once; the point is contention.
initialMaxStreamsBidi: kStreams,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h3 or quic ?

@martenrichter

martenrichter commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Great addition to find more stalls in the pipeline.
Beside the comments, the rest looks good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants