Skip to content

quic: For streams allow ReadableStream as body - #60237

Open
martenrichter wants to merge 84 commits into
nodejs:mainfrom
martenrichter:quicbodyasreadable
Open

quic: For streams allow ReadableStream as body#60237
martenrichter wants to merge 84 commits into
nodejs:mainfrom
martenrichter:quicbodyasreadable

Conversation

@martenrichter

Copy link
Copy Markdown
Contributor

After the change the body parameter for all
created QuicStreams can take a ReadableStream
of Uint8Array, Arraybuffers etc..

We introduce a DataQueueFeeder class that may be
also used for other related mechanisms.

A locally created unidirectional Stream can not
have a reader. Therefore, the interface is changed
to handle this case. (undercovered when writing
the tests).

Furthermore, a ResumeStream must be added after
AddStream in QuicSession, as the ResumeStream
beforehand triggered with set_outbound is a no-op,
as Stream was not added to Session beforehand.

Fixes: #60234

@nodejs-github-botnodejs-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 Oct 12, 2025
@martenrichter

Copy link
Copy Markdown
ContributorAuthor

@jasnell This try to add support for streams for outgoing data. I hope the PR is helpful and does not waste too much time. I have contributed long time ago 1-2 patches, but I am not that fluent with the node.js codebase.

@codecov

codecovBot commented Oct 12, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.04786% with 107 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.79%. Comparing base (4f24aff) to head (15d2cc1).
⚠️ Report is 1700 commits behind head on main.

Files with missing linesPatch %Lines
src/dataqueue/queue.cc68.01%62 Missing and 17 partials ⚠️
src/quic/streams.cc51.51%10 Missing and 6 partials ⚠️
src/node_blob.cc90.90%2 Missing and 2 partials ⚠️
src/quic/session.cc66.66%2 Missing and 2 partials ⚠️
src/dataqueue/queue.h25.00%3 Missing ⚠️
src/quic/application.cc80.00%0 Missing and 1 partial ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #60237 +/- ##
==========================================
+ Coverage 88.53% 88.79% +0.26% 
==========================================
Files 703 704 +1 Lines 208546 208884 +338 Branches 40217 40339 +122 ==========================================
+ Hits 184634 185479 +845 + Misses 15926 15296 -630 - Partials 7986 8109 +123 
Files with missing linesCoverage Δ
lib/internal/blob.js99.81% <100.00%> (+<0.01%)⬆️
lib/internal/quic/quic.js100.00% <100.00%> (ø)
src/node_binding.cc82.74% <ø> (ø)
src/quic/quic.cc100.00% <ø> (ø)
src/quic/streams.h0.00% <ø> (ø)
src/quic/application.cc45.70% <80.00%> (+25.51%)⬆️
src/dataqueue/queue.h25.00% <25.00%> (ø)
src/node_blob.cc76.70% <90.90%> (+0.95%)⬆️
src/quic/session.cc42.95% <66.66%> (+13.88%)⬆️
src/quic/streams.cc42.58% <51.51%> (+39.38%)⬆️
... and 1 more

... and 58 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.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

There is a crash on some platforms. TODO for next weekend.

@trivikrtrivikr added the quic Issues and PRs related to the QUIC implementation / HTTP/3. label Oct 14, 2025
@martenrichter

Copy link
Copy Markdown
ContributorAuthor

Locally, I do not have any crashes. Please note, that some of the commits fix errors present in the actual implementation.
I did not make separate PR as these were uncovered by the test included in the commit.
Most of them are annoying race conditions or problems with the lifetime of the objects (use after free!), though I do not see security implications as at the current stage, I do not assume a production usage of quic.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

It seems, that Linux arm is crashing (or is flaky). So probably, I have to go to a Linux container, next weekend) or something else to figure out, what is happening there. (But it may be a problem not introduced by this PR).
(I hope it is a general flakyness on Linux and not ARM specific, or specific on the timing of the runner).

@jasnell

Copy link
Copy Markdown
Member

Btw I should have time to look at this PR this upcoming weekend

@martenrichter

martenrichter commented Oct 25, 2025

Copy link
Copy Markdown
ContributorAuthor

Btw I should have time to look at this PR this upcoming weekend

This would be great. I am currently trying to reproduce the crash in a non arm container, no luck so far. I will try to use a github code space for arm, next. (Edit: no arm codespaces, but may be the x86 gives a different timing).

@martenrichter

martenrichter commented Oct 26, 2025

Copy link
Copy Markdown
ContributorAuthor

This time only unrelated MacOS failures. And I could not reproduce the previous arm faliures locally, may be the rebase
has fixed it.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

Now, Code coverage is increased, and no failing tests.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

The newly added test is actually flaky. Sending out data stalls depending on timing. I have to investigate, why SendPendingData is not called any more.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

The new test is failing as it uncovered a yet-to-be-determined race condition.
What I see is that after submitting 60000, 12, and 50000 bytes, the last submission stalls. On the receive side, 58881 bytes are received. On the send side, it is unclear whether it is flow control or if the sending is just not rescheduled in the Application object. Ideas welcome for the cause, I will continue next weekend. (Review can still start, bug fixing is unrelated.).

Note that I also found another issue (use after free) during debugging related to using next bound to Session and Stream object that are not valid anymore; this should be fixed. It could be a general pitfall when using Bob.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

I think I finally found the race condition, causing the test to fail.
Hopefully the automated test will go through.
Now I have to decide, whether I will also add tests of bidirectional streams in this PR or another one.

Comment threadsrc/quic/session.h Outdated
Comment threadsrc/quic/session.cc Outdated
Comment threadsrc/quic/session.cc Outdated
Comment threadsrc/quic/streams.h Outdated
Comment threadsrc/quic/streams.h Outdated
Comment threadsrc/quic/streams.h Outdated
Comment threadsrc/quic/streams.h Outdated
Comment threadsrc/quic/streams.cc Outdated
@@ -17,9 +17,11 @@

namespace node {

using quic::BindingData;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This using should not be necessary

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I remove it at my local copy and see what happens in the build process.

Comment threadsrc/dataqueue/queue.h
@martenrichter

Copy link
Copy Markdown
ContributorAuthor

@jasnell Any chance for a new round of review?

@achingbrain

Copy link
Copy Markdown

I'm looking forward to streaming input making it into the QUIC API here, thanks for taking the time to open this.

From an API perspective, would it make more sense to instead add a writable property to quic.QuicStream of type WritableStream?

This would mirror the WebTransportBidirectionalStreamreadable/writable properties and so be more familiar to developers used to working with duplex streams.

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

Well, I did not touch this. I followed the interface that was already there. And I also asked myself the same question. But I think under the hood in the node.js environment it may be a valid choice, as it was made with normal http3 in mind and not webtransport. Though converting it is easy, see the test, I wanted to use the familiar pattern. My main concern is that things get going at some point. As I was almost forgot what I have done here.

@achingbrain

Copy link
Copy Markdown

For sure, adding the extra body type is less disruptive so I can see why this PR takes that route, but I for one was definitely expecting to see QuicStreams being duplex streams.

As implemented they seem closer to window.fetch which is less useful for my use-case (communicating with rust/go libp2p nodes over the QUIC transport (as a better TCP) which uses the built-in bidirectional stream capability as lightweight application level multiplexed streams).

@martenrichter

Copy link
Copy Markdown
ContributorAuthor

Yes, it is more like fetch. I tried to just fill the gaps that @jasnell left. (As far as I understood them). So that you can also paste later node.js streams and async iterators.
But I do not see a problem with your use cases, I already have an idea how I can use it as a Node.js native backend for my package, where you contributed with the tests. (Note this here are quicstreams, for Webtransport, some tiny bits have to be added to the streams) .However, currently I am waiting for some signals on how the quic support will progress.

Sign up for freeto 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 / srcIssues and PRs related to general changes in the lib or src directory.needs-ciPRs that need a full CI run.quicIssues and PRs related to the QUIC implementation / HTTP/3.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

quic: body is lacking support for streaming

5 participants

@martenrichter@jasnell@achingbrain@trivikr@nodejs-github-bot