(First of all, stream-to-it and it-pipe are amongst my favourite NPM packages: My code would've been really complicated had you not made these packages available, so thank you so much!)
I'm implementing a WebSocket-based protocol using ws. ws offers a duplex stream to communicate with the peer and I'm wrapping that stream in a "duplex iterable" (generated by duplex()), which I pass to it-pipe.
The code mostly works as expected, but I'm running into two related issues:
If the duplex' sink completes normally, Node.js would call duplex.end(), which will cause ws to close the connection normally -- Even if we're waiting for messages from the source. For example, the protocol I'm implementing sends messages that must be acknowledged by the peer, so if we're done sending messages we should still keep the connection open to receive outstanding ACKs.
I think both issues could be solved if duplex() supported an option that wouldn't call destroy()/end() on the underlying stream (maybe as a pass-through stream). That'd allow me to do something like this on the server:
const wsDuplex = WebSocket.createWebSocketStream(ws);
try {
await pipe(loadMessages, duplex(wsDuplex, {allowClosing: false}), processAcknowledgements)
// If we get to this point, processAcknowledgements() must've ended the loop
ws.close(1000, 'All good')
} catch (err) {
ws.close(1008, 'Something went wrong')
}
(duplex.end() will still be called when the connection is closed. OTOH, the example above is overly simplified: I'd probably have to use an AbortableController to signal the source of the duplex iterable when the client closes the connection.)
(First of all,
stream-to-it
andit-pipe
are amongst my favourite NPM packages: My code would've been really complicated had you not made these packages available, so thank you so much!)I'm implementing a WebSocket-based protocol using
ws
.ws
offers a duplex stream to communicate with the peer and I'm wrapping that stream in a "duplex iterable" (generated byduplex()
), which I pass toit-pipe
.The code mostly works as expected, but I'm running into two related issues:
break
in the loop, Node.js would callduplex.destroy()
, which will causews
to close the connection abruptly.duplex.end()
, which will causews
to close the connection normally -- Even if we're waiting for messages from the source. For example, the protocol I'm implementing sends messages that must be acknowledged by the peer, so if we're done sending messages we should still keep the connection open to receive outstanding ACKs.I think both issues could be solved if
duplex()
supported an option that wouldn't calldestroy()
/end()
on the underlying stream (maybe as a pass-through stream). That'd allow me to do something like this on the server:(
duplex.end()
will still be called when the connection is closed. OTOH, the example above is overly simplified: I'd probably have to use anAbortableController
to signal the source of the duplex iterable when the client closes the connection.)Thoughts?