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
Interest in support for .send()
-ing a stream and receiving a message as a stream?
#1832
Comments
I prefer to keep
I also think it does not make sense to have listeners of the |
You're right about
The websocket protocol is indeed message-based, but those messages can have any size, so In my context, I'm sending files over a websocket as one message (potentially many frames of course). With send, I can manually split it into chunks, but for receiving the message, |
You can set
This is true if you use fragmented messages. The The first message could be an info message with the file name and size in bytes. Subsequent messages could be the file contents, one for each chunk read from the |
@loganfsmyth , that is an interesting idea, but, since you are asknig for opinions:
the reason is easy to explain. There is only ONE thing we want from the amazing /ws. RELIABILITY! I can easily write a few lines of code to deal with issues such as long messages, etc. All I want from the amazing /ws is continued total reliability! I hope that makes sense. Just one opinion! |
My biggest goal is to not have to hold the whole message in memory, so while this will work, it won't achieve that goal if many clients were to send large files at the same time, it could overwhelm the box quickly if we did this.
You're right that it's an option, but I'd rather not be pushed to define my messaging format based on the limitations of
I'm not sure what definition of reliable you have in mind, but I'd consider the requirement that a message be fully aggregated in memory to be detrimental to reliability because you more easily run the risk of overloading the RAM of the machine. Node itself is heavily dependent on streams as a concept, so I'm just generally surprised that they aren't supported as a first-class type in WS. |
I'd rather say that it's a limitation of the
It is not that different. Compare your ideal solution which sends many fragments to something like this that sends many messages. // Writing end.
const info = JSON.stringify({ filename: 'big.iso', size: 10737418240 });
const websocketStream = WebSocket.createWebSocketStream(ws);
ws.send(info, function (err) {
if (err) {
handleError(err);
return;
}
const fileStream = fs.createReadStream('big.iso');
fileStream.pipe(websocketStream, { end: false });
}); // Reading end.
let filename;
let size;
let bytesRead = 0;
let fileStream;
const websocketStream = WebSocket.createWebSocketStream(ws);
websocketStream.on('data', function (chunk) {
if (typeof chunk === 'string') {
({ filename, size } = JSON.parse(chunk));
fileStream = fs.createWriteStream(filename);
} else {
bytesRead += chunk.length;
if (!fileStream.write(chunk)) {
websocketStream.pause();
fileStream.on('drain', function () {
websocketStream.resume();
});
}
if (bytesRead === size) {
fileStream.end();
bytesRead = 0;
}
}
}); |
How do you define when you do and don't follow the spec? The spec doesn't return a boolean from
I'd say that a message is a sequence of fragments, but how that sequence is exposed is entirely up to the library. The current behavior absolutely makes sense as the default, but that doesn't mean it needs to be limited to that. All of the current behaviors are trivially implementable on top of a stream of fragments, but not the other way around.
I'm not trying to say this would be the default or a breaking change, I'm proposing it as an opt-in feature, since I do agree that for many usecases, the streaming aspect of things is not important. I don't personally see much benefit to a
It is primarily the |
browser clients return the full message when a fragmented message is received.
No,
Returning a
|
Because the spec was written before streams in the browser were an option. I think in the context of streams being common in Node, it's an understandable request.
Ah my mistake, I misremembered about My point is, clearly you've expanded the API to include things that are non-standard, so it doesn't seem like supporting streams is necessarily beyond scope here.
Can you elaborate on the complexity? It is managing the async state transitions beyond the existing cases that is the concern?
I'd expect that Receiver would delay calling the callback passed to _write until the data is pushed into the readable stream, and if push returns false, the callback would not be called until
I'd probably say discard further fragments that arrive in that message.
I haven't looked into that, but it seems like ws would have to validate the fragments as they arrive, carrying over any incomplete utf8 sequences to prepend to the next fragment, like Node's StringDecoder does. If the message is incorrect, the stream can error and the connection would close, similar to now. I guess it's a bit unclear whether the error would be emitted on both the socket and the readable stream though. |
Yes, Node.js streams are complex and have a lot of edge cases. This feature also affects the current streaming interface as the wrapping
There are some edge cases that must be handled correctly to avoid dead locks and to ensure that the callback of The Probably a lot of other things I can't think of at the moment.
Yes but there is no such validator at the moment, it must be written. Overall it's a lot of work and complexity that is not needed in my opinion. |
Fair enough. Sounds like this is a no-go. I appreciate you taking the time to talk to me about it. |
Thank you for the constructive discussion. |
issue.
Description
For receiving larger payloads in messages, it's not ideal that you end up having to worry about
maxPayload
and having buffer it all in memory before emitting the "message" event, and for sending larger payloads, it is a bit of a pain to manually chunk things up and to manually coordinate the 'fin' bit. Using streams also means that we get backpressure support which would be wonderful.I was thinking of playing around with implementing support for
.send()
to accept a Readable stream, and formessage
events to emit a Readable stream, if a flag were set.binaryType
could potentially be reused, but I could also see it being nice to stream text messages, so maybe a separatetextType: "stream"
would be desirable.Thoughts? Has this been discussed anywhere in the past? I looked but everything stream related seems to be about WebSocketStream.
The text was updated successfully, but these errors were encountered: