mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
stream: fixup writer to terminate on consumer return/throw
Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode PR-URL: https://github.com/nodejs/node/pull/65652 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
1 parent
ae168eac5b
commit
535f934000
2 files changed
+47
-19
No files matched your search
@@ -425,6 +425,13 @@ class PushQueue {
|
||||
// ===========================================================================
|
||||
|
||||
async read() {
|
||||
if (this.#consumerState === 'returned') {
|
||||
return { __proto__: null, done: true, value: undefined };
|
||||
}
|
||||
if (this.#consumerState === 'thrown') {
|
||||
throw this.#error;
|
||||
}
|
||||
|
||||
// If there's data in the buffer, return it immediately
|
||||
if (this.#slots.length > 0) {
|
||||
const result = this.#drain();
|
||||
@@ -458,16 +465,9 @@ class PushQueue {
|
||||
consumerReturn() {
|
||||
if (this.#consumerState !== 'active') return;
|
||||
this.#consumerState = 'returned';
|
||||
this.#cleanup();
|
||||
const error = new ERR_INVALID_STATE.TypeError('Stream closed by consumer');
|
||||
this.#terminateWriterFromConsumer(error);
|
||||
this.#resolvePendingReads();
|
||||
this.#rejectPendingWrites(
|
||||
new ERR_INVALID_STATE.TypeError('Stream closed by consumer'));
|
||||
// If closing, reject the pending end promise
|
||||
if (this.#writerState === 'closing' && this.#pendingEnd) {
|
||||
this.#pendingEnd.reject(
|
||||
new ERR_INVALID_STATE.TypeError('Stream closed by consumer'));
|
||||
this.#pendingEnd = null;
|
||||
}
|
||||
// Resolve pending drains with false - no more data will be consumed
|
||||
this.#resolvePendingDrains(false);
|
||||
}
|
||||
@@ -476,13 +476,8 @@ class PushQueue {
|
||||
if (this.#consumerState !== 'active') return;
|
||||
this.#consumerState = 'thrown';
|
||||
this.#error = error;
|
||||
this.#cleanup();
|
||||
this.#terminateWriterFromConsumer(error);
|
||||
this.#rejectPendingReads(error);
|
||||
this.#rejectPendingWrites(error);
|
||||
if (this.#writerState === 'closing' && this.#pendingEnd) {
|
||||
this.#pendingEnd.reject(error);
|
||||
this.#pendingEnd = null;
|
||||
}
|
||||
// Reject pending drains - the consumer errored
|
||||
this.#rejectPendingDrains(error);
|
||||
}
|
||||
@@ -516,9 +511,30 @@ class PushQueue {
|
||||
return size;
|
||||
}
|
||||
|
||||
#terminateWriterFromConsumer(error) {
|
||||
this.#slots.clear();
|
||||
this.#bufferedBytes = 0;
|
||||
if (this.#writerState === 'open' || this.#writerState === 'closing') {
|
||||
this.#writerState = 'errored';
|
||||
this.#error = error;
|
||||
}
|
||||
this.#cleanup();
|
||||
this.#rejectPendingWrites(error);
|
||||
if (this.#pendingEnd) {
|
||||
this.#pendingEnd.reject(error);
|
||||
this.#pendingEnd = null;
|
||||
}
|
||||
}
|
||||
|
||||
#resolvePendingReads() {
|
||||
while (this.#pendingReads.length > 0) {
|
||||
if (this.#slots.length > 0) {
|
||||
if (this.#consumerState === 'returned') {
|
||||
const pending = this.#pendingReads.shift();
|
||||
pending.resolve({ __proto__: null, done: true, value: undefined });
|
||||
} else if (this.#consumerState === 'thrown') {
|
||||
const pending = this.#pendingReads.shift();
|
||||
pending.reject(this.#error);
|
||||
} else if (this.#slots.length > 0) {
|
||||
const pending = this.#pendingReads.shift();
|
||||
const result = this.#drain();
|
||||
this.#resolvePendingWrites();
|
||||
@@ -533,9 +549,6 @@ class PushQueue {
|
||||
} else if (this.#writerState === 'errored') {
|
||||
const pending = this.#pendingReads.shift();
|
||||
pending.reject(this.#error);
|
||||
} else if (this.#consumerState === 'returned') {
|
||||
const pending = this.#pendingReads.shift();
|
||||
pending.resolve({ __proto__: null, done: true, value: undefined });
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user