-
Notifications
You must be signed in to change notification settings - Fork 611
Description
In the current implementation of the WebSocket protocol, the server can send or receive entire messages only, which is a pitty considering the consumption of memory caused by assembling those byte arrays in full just to deserialize or serialize JS objects from/into them. Multiply this by the number of concurrent connections, which should be in the thousands.
Also consider the case where people need to send fair amounts of data (like files) on the connection. Yes, there are other protocols designed for file transfer, but WebSocket is more versatile 😉
My proposal is to bring streaming behaviour to this package by adding API for sending and receiving messages by fragments:
- A new
sendByFragments
method onWebSocket
which parallels the existing send:
sendByFragments(message: AsyncIterable<RecognizedString>, isBinary?: boolean, compress?: boolean) : Promise<number>
,
along with an enhancement to the currentsend
to also accept anIterable<RecognizedString>
as message
send(message: RecognizedString|Iterable<RecognizedString>, isBinary?: boolean, compress?: boolean) : number
,
for the case when the serialized data is already loaded in memory (needs not be fetched from some storage).
👉 Mind that someRecognizedString
s areIterable
, so the fragmented variant should be executed when themessage
parameter is not aRecognizedString
.
In both variants iteration should be suspended when the message fragment is dropped due to backpressure, by callingreturn()
on the iterator (call it without any guard, so as to crash whenreturn()
isn't defined). This is in line with the behaviour of a ReadableStream's asynchronous iterator. - A new
messageFragments
property onWebSocketBehavior
, mutually exclusive withmessage
:
messageFragments?: (ws: WebSocket<UserData>, isBinary: boolean) => ((fragment: ArrayBuffer, isLast: boolean) => void | Promise<void>))
It returns a handler for message fragments which µWebSockets.js can call for every received fragment of a message (with the first call expected immediately after this method returns).
The fragments of a WebSocket message need not reflect the boundaries of frames that make up that message (you can have continuation frames after a message frame). The relationship between fragmentation and WebSocket frames should be decided internally by your implementation, perhaps steered by a new configuration value specified in WebSocketBehavior
.