-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
http: fix drain event with cork/uncork in ServerResponse #60437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Review requested:
|
mcollina
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
|
@ThierryMT can you add a test? |
When using cork() and uncork() with ServerResponse, the drain event was not reliably emitted after uncorking. This occurred because the uncork() method did not check if a drain was pending (kNeedDrain flag) after flushing the chunked buffer. This fix ensures that when uncork() successfully flushes buffered data and a drain was needed, the drain event is emitted immediately. Fixes: nodejs#60432
63b516b to
972f733
Compare
Add test to verify that the drain event is properly emitted when using cork() and uncork() with ServerResponse.
pimterry
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix LGTM 👍
Test looks good if we can avoid the branch, but there are some lint warnings here on the test JS & the commit message that will need fixing before we can merge this.
| // Write large amount that should require drain | ||
| const needsDrain = !res.write('2'.repeat(1000000)); | ||
|
|
||
| if (needsDrain) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should always need drain right? It's corked so there's no race condition or anything.
Unless there's a good reason, imo it would be better to enforce that (assert.strictEqual(res.write('2'.repeat(1000000)), false)) and drop the if here entirely.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #60437 +/- ##
==========================================
- Coverage 88.58% 88.57% -0.02%
==========================================
Files 704 704
Lines 207815 207832 +17
Branches 40036 40042 +6
==========================================
- Hits 184102 184096 -6
- Misses 15758 15785 +27
+ Partials 7955 7951 -4
🚀 New features to boost your workflow:
|
Ethan-Arrowood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks good. can you fix the formatting in the test file?
Fixes #60432
When using
cork()anduncork()withServerResponse, thedrainevent was not reliably emitted after uncorking. This occurred because theuncork()method did not check if a drain was pending (kNeedDrainflag) after flushing the chunked buffer.The Problem:
write()buffers data inkChunkedBufferinstead of sending immediatelywrite()returnsfalse,kNeedDrainis set totrueuncork()is called, it flushes the buffer by calling_send()uncork()never checked if drain was needed or emitted the eventdrainevent that would never fireThe Fix:
This commit ensures that when
uncork()successfully flushes buffered data and a drain was needed, thedrainevent is emitted immediately.Changes:
OutgoingMessage.prototype.uncork()inlib/_http_outgoing.js_send()calldrainevent when appropriateTesting:
The issue could be reproduced by using
cork()with multiple large writes and checking fordrainevents. With this fix, thedrainevent now fires correctly afteruncork().