Skip to content

Commit daed51b

Browse files
committed
http: Simplify drain-on-uncork logic and test
Check internal state when deciding whether to send a drain event on uncork() - instead of relying on the return value of _send - as suggested in the PR comments. The test is updated to set an explicit high water mark for better reliability, and since this means we can use a much lower value, the size of data in the test has been reduced significantly.
1 parent 3dd6cb4 commit daed51b

2 files changed

Lines changed: 19 additions & 22 deletions

File tree

lib/_http_outgoing.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ OutgoingMessage.prototype.uncork = function uncork() {
315315
callbacks.push(buf[n + 2]);
316316
}
317317
}
318-
const ret = this._send(crlf_buf, null, callbacks.length ? (err) => {
318+
this._send(crlf_buf, null, callbacks.length ? (err) => {
319319
for (const callback of callbacks) {
320320
callback(err);
321321
}
@@ -324,8 +324,8 @@ OutgoingMessage.prototype.uncork = function uncork() {
324324
this[kChunkedBuffer].length = 0;
325325
this[kChunkedLength] = 0;
326326

327-
// If we successfully flushed and had pending drain, emit it
328-
if (ret && this[kNeedDrain]) {
327+
// If we had a pending drain and flushed all data, emit the drain event.
328+
if (this[kNeedDrain] && this.writableLength === 0) {
329329
this[kNeedDrain] = false;
330330
this.emit('drain');
331331
}

test/parallel/test-http-response-drain-cork.js

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ const server = http.createServer(common.mustCall(async (req, res) => {
1010
res.cork();
1111

1212
// Write small amount - won't need drain
13-
assert.strictEqual(res.write('1'.repeat(100)), true);
13+
assert.strictEqual(res.write('1'.repeat(10)), true);
1414

15-
// Write large amount that should require drain
16-
assert.strictEqual(res.write('2'.repeat(1000000)), false);
15+
// Write enough to exceed highWaterMark (set in 'connection' listener)
16+
assert.strictEqual(res.write('2'.repeat(1000)), false);
1717

1818
// Verify writableNeedDrain is set
1919
assert.strictEqual(res.writableNeedDrain, true);
@@ -27,24 +27,22 @@ const server = http.createServer(common.mustCall(async (req, res) => {
2727
}));
2828
});
2929

30-
// Uncork should trigger drain if needed
30+
// Uncork should trigger drain
3131
res.uncork();
32-
3332
await drainPromise;
3433

35-
// Cork again for next write
36-
res.cork();
37-
38-
// Write more data
39-
res.write('3'.repeat(100));
40-
41-
// Final uncork and end
42-
res.uncork();
4334
res.end();
4435
}));
4536

46-
server.listen(0, common.mustCall(() => {
37+
server.on('connection', common.mustCall((socket) => {
38+
// Set high water mark large enough to cover HTTP overhead + first
39+
// small content batch, but not enough to cover second batch.
40+
socket._writableState.highWaterMark = 1000;
41+
}));
42+
43+
server.listen(0, common.localhostIPv4, common.mustCall(() => {
4744
http.get({
45+
host: common.localhostIPv4,
4846
port: server.address().port,
4947
}, common.mustCall((res) => {
5048
let data = '';
@@ -56,12 +54,11 @@ server.listen(0, common.mustCall(() => {
5654

5755
res.on('end', common.mustCall(() => {
5856
// Verify we got all the data
59-
assert.strictEqual(data.length, 100 + 1000000 + 100);
60-
assert.strictEqual(data.substring(0, 100), '1'.repeat(100));
61-
assert.strictEqual(data.substring(100, 1000100), '2'.repeat(1000000));
62-
assert.strictEqual(data.substring(1000100), '3'.repeat(100));
57+
assert.strictEqual(data.length, 10 + 1000);
58+
assert.strictEqual(data.substring(0, 10), '1'.repeat(10));
59+
assert.strictEqual(data.substring(10), '2'.repeat(1000));
6360

64-
server.close();
61+
server.close(common.mustCall());
6562
}));
6663
}));
6764
}));

0 commit comments

Comments
 (0)