-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
stream: Fix schizophrenic _read() callback behavior #4838
Conversation
…stent With this change every time _read(n, cb) is called you are expected to eventually call the callback before another _read() will be called. As a new option, you when you omit the callback in your _read() function definition the Readable will infer a sync callback with empty data right after you return.
|
There are a few problems with this:
I think that the semantics already are actually fine. If you have complaints about the semantics now, it would be best to start with a failing test, and we can discuss first whether the existing behavior is a problem or by design. I like how onread and push are split up into parts here. It'd be good to do that, but in a few separate steps, without changing anything else. |
|
Thanks for taking the time to review. I was not expecting this to be pushed just like that. For a test that fails, check the modified |
|
I think that this is a contrived edge case. If you have data available from whatever the source is, you should put it into the stream right now. If you can't guarantee the order of the actual data, then you can't guarantee the order of the data in the stream, and it ought to behave as your test is showing. All your proving is that a stream that pushes its data out of order will have data out of order. |
|
From a user POV, I still find the duplicity of I'm not saying that push followed by an async callback is a good way to design your _read handler, but I expect that future implementors might experiment with this, and find it doesn't behave as they thought. Also, the solution might just be clearer documentation. |
I agree. In fact, I'd push for undocumenting the An even better idea would be to implement a subclass of Readable: PushReadable. And that's where the |
|
@TooTallNate Thanks for the support, and I like the idea of a PushReadable with a clean implementation. As I see it A potential issue with a PushReadable, is the other subclasses. Ie. will you have to create a PushDuplex and PushTransform as well? |
|
When you get down to it, The solution here is to remove the callback to Care to review? #4878 It's easy enough to implement |
There is a need to clarify the relationship between
push(),_read(), and its callback. I propose the attached patch, which tries to limit the changes needed for existing extensions.Reasoning
Currently, the
read()callback is used inconsistently when combined withpush(). Ifpush()is used, it will signal that any pending_read()has happened, resulting in a new_read()call before any async callbacks have been handled.This is illustrated in the attached revision to the
test-stream-push-order.jstest which fails on master.The problem can be fixed by always waiting for the callback before calling _read() again but this would break the pattern described in the
push()documentation, since it never calls the callback.The patch
With this patch, every time
_read(n, cb)is called you are expected to eventually call the callback before another_read()will be called.As a new option, you when you omit the callback in your
_read()function definition the Readable will infer a sync callback with empty data right after you return. This allows thepush()pattern to continue working by simply removing the arguments.As a sidenote, this also fixes
_read()being called incorrectly duringpush()'es.