uNetworking / uWebSockets.js

μWebSockets for Node.js back-ends :metal:
Apache License 2.0
8.08k stars 573 forks source link

Possible to "cleanly" detect when a WebSocket is closed #539

Closed tayler-king closed 3 years ago

tayler-king commented 3 years ago

Say I have a websocket that follows this process:

  1. Socket connects
  2. Socket asynchronously subscribes to topic
  3. Socket exchanges data with application
  4. Socket disconnects

This works well and fine. However in some conditions, as the socket subscription is asynchronous, the following happens:

  1. Socket connects
  2. Socket asynchronously subscribes to topic
  3. Socket disconnects whilst above operation is occurring
  4. Exception is thrown: Invalid access of closed uWS.WebSocket/SSLWebSocket.

I say the subscription is "asynchronous" for the following reasons:

  1. Socket connects
  2. Socket sends message to server, requesting to subscribe to a specific topic
  3. Server processes subscription request, performs asynchronous operation
  4. The application then calls socket.subscribe(topic) once the asynchronous operation completes

As you can see, if the socket disconnects during step 3 then attempting to call socket.subscribe(topic) results in an exception being thrown.

Now obviously I could just handle that exception but I would much prefer if I could pre-emptively check if the socket is closed prior to calling socket.subscribe(topic).

Is this at all possible? From taking a quick glance at the codebase it doesn't seem so. Maybe having a socket.isClosed flag on socket objects would be possible?

I could also track this myself, but it seems like unnecessary complexity that would possibly be better suited in the uWebSockets.js extension?

hst-m commented 3 years ago

unnecessary complexity

the standard thing to do if doing async before using socket is set ws.isClosed=true in the close handler and check it after async, not that complex

close:ws=>ws.isClosed=true

await async()
if(!ws.isClosed)ws.subscribe(topic)
tayler-king commented 3 years ago

the standard thing to do if doing async before using socket is set ws.isClosed=true in the close handler and check it after async, not that complex

close:ws=>ws.isClosed=true

await async()
if(!ws.isClosed)ws.subscribe(topic)

Does mutating the socket object passed to one handler guarantee that the object mutation will carry across to the other handles? As an example:

  1. Socket object obtained from message callback, attempts to subscribe to topic
  2. Socket object obtained from close callback is mutated, socket.isClosed is set to true
  3. Original socket object from step 1 attempts to check socket.isClosed during its async operation
hst-m commented 3 years ago

its the same JS object being passed around, so yes different functions access same ws object with updated properties

tayler-king commented 3 years ago

its the same JS object being passed around, so yes different functions access same ws object with updated properties

Great, thank you. I'll close this issue as that should suffice.