I want to handle differently different cases of WebSocket connection termination. I should send email if it's terminated on client side by logout or browser closing. And I should do nothing if it's terminated on server side (for example after the server restart).
Is there a way to detect in what way connection is terminated?
I use Rails 4.2 and em-websocket gem.
There shouldn't (by design) be a way to determine the reason for the websocket connection closing, but...
... It is possible to program some closure events into your application (both client-side and server-side), allowing you to guess other reasons.
Also, websocket disconnections can happen due to loss of connectivity (network cable unplugged, lost Wi-Fi/cellular reception, system crash etc'), a situation which is usually detected after a longer while - a connection could seem open (known as a half-open
state ) while being closed.
Most servers will detect the situation in up to a minute or so (that's long). Read more about it here.
For server shutdown, you can leverage the Karnel.trap
method. If you were using Plezi you'd probably be able to leverage an on_shutdown
in your controller (I'm biased, as I'm the author)... from your comment I've learned that em-websockets doesn't have a similar callback, and I'm sorry about that.
To use the trap
method, you catch the exit signal and perform any necessary actions before forwarding it. i.e. (it's not very DRY, you can improve on the concept):
old_int_trap = trap('INT') do
puts "do something"
old_int_trap.respond_to?(:call) && old_int_trap.call
end
old_term_trap = trap('TERM') do
puts "do something"
old_term_trap.respond_to?(:call) && old_term_trap.call
end
Or, if the server closes the connection for it's own reasons (authentication, misbehavior, etc'), you can easily set up a flag telling the on_close
(onclose
?) callback to do nothing.
Client logout is easy - send a message before logging the user out.
Browser shutdown can be the default (no other reason for closure).
Disconnections are hard, but you could keep a variable storing the time of last websocket message, allowing you to assume an issue if no messages were received for more than 30 seconds since the last message.
...
BUT:
Personally, I would consider using a completed
websocket message before actions such as emails etc'. I think "whitelisting" events is a better approach.