Skip to content

stream: improve Readable.from error handling#37158

Closed
benjamingr wants to merge 4 commits into
nodejs:masterfrom
benjamingr:fix-async-iterator-errors
Closed

stream: improve Readable.from error handling#37158
benjamingr wants to merge 4 commits into
nodejs:masterfrom
benjamingr:fix-async-iterator-errors

Conversation

@benjamingr
Copy link
Copy Markdown
Member

This pull request aligns the behaviour of Readable.from with other stream behaviours namely:

  • Errors thrown in the stream now propagate via .throw and not via .on and reach catch blocks. This means things like addAbortSignal work with Readable.from now.
  • The generator is always closed, even if next was not called - this is because the previous implementation had a timing bug where if next was called and the stream was destroyed in the same tick - finally blocks would not run.

cc @ronag @mcollina @nodejs/streams

@benjamingr benjamingr added the stream Issues and PRs related to the stream subsystem. label Jan 31, 2021
Comment thread lib/internal/streams/from.js
};

async function close() {
async function close(error) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is tricky and I want feedback on the semantics, basically:

  • If we had an error ( .destroy(err) ) we call .throw - this aligns the behaviour of .from with other methods and means stuff like addAbortSignal automagically "works".
  • If after calling throw the iterator did not finish - we also call .return
if (done) {
readable.push(null);
} else if (readable.destroyed) {
await close();
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This check is no longer necessary without needToClose since _destroy is called and if the stream is destroyed the iterator is closed.

Copy link
Copy Markdown
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread lib/internal/streams/from.js Outdated
Comment thread lib/internal/streams/from.js Outdated
Copy link
Copy Markdown
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

Comment thread lib/internal/streams/from.js Outdated

async function close() {
async function close(error) {
const hadError = typeof error !== 'undefined';
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.

Wouldn't error be null?

const result = self._destroy(err || null, (err) => {

@aduh95 aduh95 force-pushed the fix-async-iterator-errors branch from 3f712a5 to 0bce498 Compare February 1, 2021 14:30
@aduh95
Copy link
Copy Markdown
Contributor

aduh95 commented Feb 1, 2021

I've rebased and force pushed to solve to git conflicts introduced by my PR.

@benjamingr
Copy link
Copy Markdown
Member Author

@aduh95 very kind of you, thanks 🙇‍♂️

@benjamingr
Copy link
Copy Markdown
Member Author

benjamingr commented Feb 2, 2021

@mcollina I might be a bit overcautious* - but I prefer to err on the side of caution.

What steps can I take to ensure there is less breakage here?

Thoughts:

Anything else?

(since the old behaviour was just an overlooked bug/edge-case and probably not relied on)

@benjamingr benjamingr added the blocked PRs that are blocked by other issues or PRs. label Feb 2, 2021
@benjamingr
Copy link
Copy Markdown
Member Author

Putting "blocked" so this doesn't land by accident in the meantime.

@benjamingr
Copy link
Copy Markdown
Member Author

I went through most CITGM failures and there don't seem to be new/related ones

@mcollina
Copy link
Copy Markdown
Member

mcollina commented Feb 3, 2021

I do not think we have any modules using this in CITGM. It's not touching any old/critical APIs, so it should be good to land.

@mcollina mcollina removed the blocked PRs that are blocked by other issues or PRs. label Feb 3, 2021
@benjamingr
Copy link
Copy Markdown
Member Author

Thanks matteo. Landed in 03380bc

@benjamingr benjamingr closed this Feb 3, 2021
benjamingr added a commit that referenced this pull request Feb 3, 2021
PR-URL: #37158
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@benjamingr benjamingr deleted the fix-async-iterator-errors branch February 3, 2021 11:23
@benjamingr benjamingr added the semver-minor PRs that contain new features and should be released in the next minor version. label Feb 3, 2021
danielleadams pushed a commit that referenced this pull request Feb 16, 2021
PR-URL: #37158
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
danielleadams added a commit that referenced this pull request Feb 16, 2021
Notable Changes:

* crypto:
  * add keyObject.export() 'jwk' format option (Filip Skokan) #37081
* deps:
  * upgrade to libuv 1.41.0 (Colin Ihrig) #37360
* doc:
  * add dmabupt to collaborators (Xu Meng) #37377
  * refactor fs docs structure (James M Snell) #37170
* fs:
  * add fsPromises.watch() (James M Snell) #37179
  * use a default callback for fs.close() (James M Snell) #37174
  * add AbortSignal support to watch (Benjamin Gruenbaum) #37190
* perf_hooks:
  * introduce createHistogram (James M Snell) #37155
* stream:
  * improve Readable.from error handling (Benjamin Gruenbaum) #37158
* timers:
  * introduce setInterval async iterator (linkgoron) #37153
* tls:
  * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
This was referenced Feb 16, 2021
danielleadams added a commit that referenced this pull request Feb 17, 2021
Notable Changes:

* crypto:
  * add keyObject.export() 'jwk' format option (Filip Skokan) #37081
* deps:
  * upgrade to libuv 1.41.0 (Colin Ihrig) #37360
* doc:
  * add dmabupt to collaborators (Xu Meng) #37377
  * refactor fs docs structure (James M Snell) #37170
* fs:
  * add fsPromises.watch() (James M Snell) #37179
  * use a default callback for fs.close() (James M Snell) #37174
  * add AbortSignal support to watch (Benjamin Gruenbaum) #37190
* perf_hooks:
  * introduce createHistogram (James M Snell) #37155
* stream:
  * improve Readable.from error handling (Benjamin Gruenbaum) #37158
* timers:
  * introduce setInterval async iterator (linkgoron) #37153
* tls:
  * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
danielleadams added a commit that referenced this pull request Feb 17, 2021
Notable Changes:

* crypto:
  * add keyObject.export() jwk format option (Filip Skokan) #37081
* deps:
  * upgrade to libuv 1.41.0 (Colin Ihrig) #37360
* doc:
  * add dmabupt to collaborators (Xu Meng) #37377
  * refactor fs docs structure (James M Snell) #37170
* fs:
  * add fsPromises.watch() (James M Snell) #37179
  * use a default callback for fs.close() (James M Snell) #37174
  * add AbortSignal support to watch (Benjamin Gruenbaum) #37190
* perf_hooks:
  * introduce createHistogram (James M Snell) #37155
* stream:
  * improve Readable.from error handling (Benjamin Gruenbaum) #37158
* timers:
  * introduce setInterval async iterator (linkgoron) #37153
* tls:
  * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
danielleadams added a commit that referenced this pull request Feb 17, 2021
PR-URL: #37406

Notable Changes:

* crypto:
  * add keyObject.export() jwk format option (Filip Skokan) #37081
* deps:
  * upgrade to libuv 1.41.0 (Colin Ihrig) #37360
* doc:
  * add dmabupt to collaborators (Xu Meng) #37377
  * refactor fs docs structure (James M Snell) #37170
* fs:
  * add fsPromises.watch() (James M Snell) #37179
  * use a default callback for fs.close() (James M Snell) #37174
  * add AbortSignal support to watch (Benjamin Gruenbaum) #37190
* perf_hooks:
  * introduce createHistogram (James M Snell) #37155
* stream:
  * improve Readable.from error handling (Benjamin Gruenbaum) #37158
* timers:
  * introduce setInterval async iterator (linkgoron) #37153
* tls:
  * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
danielleadams added a commit that referenced this pull request Feb 18, 2021
PR-URL: #37406

Notable Changes:

* crypto:
  * add keyObject.export() jwk format option (Filip Skokan) #37081
* deps:
  * upgrade to libuv 1.41.0 (Colin Ihrig) #37360
* doc:
  * add dmabupt to collaborators (Xu Meng) #37377
  * refactor fs docs structure (James M Snell) #37170
* fs:
  * add fsPromises.watch() (James M Snell) #37179
  * use a default callback for fs.close() (James M Snell) #37174
  * add AbortSignal support to watch (Benjamin Gruenbaum) #37190
* perf_hooks:
  * introduce createHistogram (James M Snell) #37155
* stream:
  * improve Readable.from error handling (Benjamin Gruenbaum) #37158
* timers:
  * introduce setInterval async iterator (linkgoron) #37153
* tls:
  * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-minor PRs that contain new features and should be released in the next minor version. stream Issues and PRs related to the stream subsystem.

7 participants