-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
Recent behavior change of buffered write callbacks #31317
Comments
cc: @nodejs/streams @ronag |
For me this is less about a specific case and more about whether all async apis should always call the callback or not. Callbacks always being invoked is what I would expect and wouldn't even normally consult the documentation (even though that is probably a good idea). Though I would prefer for callbacks to always be invoked, I'm not strongly against reverting. Not always calling the callback would make the code simpler and the documentation does state that the "the callback may or may not be called with the error as its first argument". -0 Not sure about #29028. If revert, would probably change that so that the buffered writes are removed but the callbacks are not invoked. |
I LGTM the original change, however this issue highlight several interesting points. As it is implemented in 12, I think that the callback of Somebody might write this code: function shutdown(stream) {
stream.write('SHUTDOWN', function() {
db.teardown() // note that this will cause a memory leak if not called.
stream.end()
})
} This code is not safe as a developer would need to add a lot of checks to make it safe. Note that our docs does not say it any place that the callback is advisory-only and it might not be called at all. It does not mention that this callback might not be called if the stream errors, it has ended, etc. I don't use the
This is true. However the callbacks that might not be called at all are also the ones that can be called many times. Take the callback in Not calling callbacks creates situations where we do not know what's the state inside things, making it impossible to rely on that API. Moreover, a tool like The most valuable point for me is backward compatibility:
Have you got any specific code that relies on the unreliable behavior? |
If that callback is not called it means the stream had buffered writes and it already errored from a previous write or was destroyed and the developer must handle that case anyway.
I disagree. This sentence
was added in b801e39 and from commit message it was explicitly made vague to keep that case (callback not called if the stream errors) possible.
It is reliable at least with the streams I've used (mainly
Yes, in To make it consistent with the new behavior we can call all buffered send callbacks but
|
I wouldn't be opposed to this as well as doc-deprecate the callback for |
I would revert but if that is not an option then go ahead, close this, and remove the blocked label from #31179. I don't want to keep it on hold indefinitely. |
Would you like to get this escalated to the tsc about doing a revert? |
Yes I think it would be nice to have TSC feedback here. |
Hey fellow @nodejs/tsc members, @lpinca is asking our opinion in this regard. In #29028 and #30596, he would have objected to them landing, and he is asking if we should do a revert. The changes landed on Node 13. Note that both PRs were approved by @jasnell @addaleax and myself. I've added this to discuss in the next meeting. |
We discussed this in the last tsc meeting nodejs/TSC#828. While we did not vote, there was no objection to provide the following feedback. We think that the write callbacks should be called and we are reluctant to revert. We recognize that it might cause backward compatibility problems, and we would like to discuss any mechanism to reduce any compatibility issues. |
Ok, I've remove the blocked label from #31179 so that it can land. |
I've removed the tsc-agenda label, but if anyone wants this on the agenda for the next meeting, just re-add it. Thanks. |
As requested by @mcollina in #31179 (comment) I'm opening this issue to discuss the possibility of reverting a recent behavior change of writable streams.
writable.write() takes an optional callback which, quoting the documentation, is a
The documentation further clarifies the callback behavior as follows:
This is quite accurate and inline with the actual implementation. There can only be a single write at time so if
writable.write()
is called while a write is in progress that write is buffered. If the stream errors or is destroyed the callbacks of buffered writes are not called.In #29028 and then in #30596 this behavior was changed to call the callbacks of buffered writes with an error.
In my opinion this change was not need or better not justified by a specific issue. From what I've gathered (correct me if I am wrong) the main reason behind the change was that code like this
could result in a promise that is never settled, but the destination stream in the example does not buffer writes so the callback is always called.
I think this change creates more problems than it solves:
write(cb)
not called ifdestroy()
:ed before'connect'
#30841 or [v13.x backport] stream: invoke buffered write callbacks on error #31179 (comment).net.Socket
buffered write callbacks are now called with an error if a write error occurs. Doing the same on Node.js < 13 will be hard and hacky for userland libs. They should wait until Node.js 12 goes EOL to have the same behavior across all supported Node.js versions.Refs: #29028
Refs: #30596
Refs: #31179
The text was updated successfully, but these errors were encountered: