Skip to content
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

Streams: forward errors on pipe #1521

Closed

Conversation

calvinmetcalf
Copy link
Contributor

pull for nodejs/readable-stream#129 cc @iojs/streams , still need to add documentation, tests, and clean up the commits

@mscdex mscdex added the stream Issues and PRs related to the stream subsystem. label Apr 25, 2015
@@ -447,6 +447,7 @@ Readable.prototype._read = function(n) {
Readable.prototype.pipe = function(dest, pipeOpts) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably add this option to Stream.prototype.pipe as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably I forgot about that one

Adds an option for stream piping to enable errors to be pass along the pipe
chain.  Defaults it to false for it to be opt-in.  This is an option to make
our streams more in line with whatwg streams.
@@ -447,6 +447,7 @@ Readable.prototype._read = function(n) {
Readable.prototype.pipe = function(dest, pipeOpts) {
var src = this;
var state = this._readableState;
pipeOpts = pipeOpts || {};
Copy link
Contributor

Choose a reason for hiding this comment

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

should we care that in a typical use-case this would create an arbitrary object?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we also avoid an unnecessary conversion of undefined to a Boolean, I doubt it makes much difference

@rvagg
Copy link
Member

rvagg commented Apr 28, 2015

Can this be easily detected if it's set on a stream? Can I !!stream.options.forwardErrors or similar?

Also be aware that this will screw up a lot of user code that assumes that errors aren't forwarded, for example in bl which is in heavy use.

And another thing:

If the stream should pass errors down the pipe instead of throwing them.

My reading of the code says that this isn't quite accurate - errors aren't thrown if they are handled and my assumption when reading this description is that they are only forwarded if they were going to throw, i.e. if there was no other error handler. Perhaps tighten that description up a bit more.

Overall I'm weary of this, I'd love for this to have been the default behaviour of streams from the beginning but we've built a whole ecosystem around the assumption that streams don't forward errors and you need to handle them all the way down; as crappy as that is.

@chrisdickinson
Copy link
Contributor

@rvagg:

Can this be easily detected if it's set on a stream? Can I !!stream.options.forwardErrors or similar?

No. This is an option set on the pipe relationship between two streams, not on a stream itself. There's no user-accessible backing object describing that relationship, so it's not queryable.


Another concern: streams that don't support this option in pipe don't alert the user that the option isn't supported. So, if someone's using a v0.10 readable-stream (or v0.12 readable-stream) they can call oldStream.pipe(newStream, {forwardErrors: true}) and it will, at the outset, look well-configured. However, the old stream won't actually forward errors, and I imagine tracking down that idiosyncracy will be difficult.

@calvinmetcalf
Copy link
Contributor Author

Also be aware that this will screw up a lot of user code that assumes that errors aren't forwarded, for example in bl which is in heavy use.

indeed this is why it's opt in

My reading of the code says that this isn't quite accurate - errors aren't thrown if they are handled and my assumption when reading this description is that they are only forwarded if they were going to throw, i.e. if there was no other error handler. Perhaps tighten that description up a bit more.

will do

Another concern: streams that don't support this option in pipe don't alert the user that the option isn't supported. So, if someone's using a v0.10 readable-stream (or v0.12 readable-stream) they can call oldStream.pipe(newStream, {forwardErrors: true}) and it will, at the outset, look well-configured. However, the old stream won't actually forward errors, and I imagine tracking down that idiosyncracy will be difficult.

we could put an attribute on the new stream to say it supports the option

@sonewman
Copy link
Contributor

it seems a little confusing. Essentially as a feature this would be advantage to have, and brings parity to WHATWG. Is the fact that it could lead mislead an user a game changer at this stage? I assume a lot of changes could also warrant these kinds of developer confusion. It would be important for changes like this to be well advertised.

I can't think how this could otherwise be implemented without introducing this extra complexity 😕💭

@calvinmetcalf
Copy link
Contributor Author

We could give it a different method name like the equivalent whatwg stream
name pipeThrough, except maybe shorter and user friendly

On Wed, Apr 29, 2015, 4:08 PM Sam Newman [email protected] wrote:

it seems a little confusing. Essentially as a feature this would be
advantage to have, and brings parity to WHATWG. Is the fact that it could
lead mislead an user a game changer at this stage? I assume a lot of
changes could also warrant these kinds of developer confusion. It would be
important for changes like this to be well advertised.

I can't think how this could otherwise be implemented without introducing
this extra complexity [image: 😕][image: 💭]


Reply to this email directly or view it on GitHub
#1521 (comment).

@domenic
Copy link
Contributor

domenic commented Apr 29, 2015

@ForbesLindesay's prior art calls it syphon; seems reasonable.

@calvinmetcalf
Copy link
Contributor Author

@ForbesLindesay's prior art calls it syphon; seems reasonable.

I like it, syphon as alias for pipe that adds the forward error thingy

@just-boris
Copy link

This is a nice feature! It makes work with streams more consistent with promises:

getStream()
    .pipe()
    .pipe()
    .pipe()
    .on('error', onError)

and the same thing with promises

getPromise()
    .then()
    .then()
    .then()
    .catch(onError)

It's nice to have one error handler at the end of chain instead of catching error after every operation

@jasnell
Copy link
Member

jasnell commented Oct 22, 2015

@calvinmetcalf @chrisdickinson @trevnorris @rvagg ... what's the status on this one?

@calvinmetcalf
Copy link
Contributor Author

@jasnell for know I'd use pump

@rvagg
Copy link
Member

rvagg commented Oct 25, 2015

I'm torn on this one, I wish it was the default but the ship has sailed. A possible compromise might be for the behaviour to be that it'll forward errors if there are no existing error listeners on the current stream, although that creates weird state and would likely go against most users' expectations.

@calvinmetcalf
Copy link
Contributor Author

@rvagg I like that I'll update the patch to do just that

@calvinmetcalf
Copy link
Contributor Author

ok so thinking through how only forward if there are no listeners, that is going to be tricky if it's part of a pipe because currently the stream that is piping to the stream has a listener and ends up throwing the error if nobody else is

@Qard
Copy link
Member

Qard commented Nov 12, 2015

Why not just make a new function that does that automatically, with the intent of eventually deprecating the current pipe function? (Obviously on a very long deprecation cycle, since streams are everywhere.)

It's fine to fear breaking things, but I think we might fear changing things a bit too much at times. With time, we can steer the community toward newer and better ways.

@denis-sokolov
Copy link

@calvinmetcalf, do you mind stating in a sentence or two the resolution of this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants