0

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.

Sergei Struk
  • 358
  • 4
  • 12

1 Answers1

1

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.

Myst
  • 18,516
  • 2
  • 45
  • 67
  • Thank you for detailed explanation! I've tried to use Kernel.at_exit method, but it works in the very end, after invocation of the onclose callback. em-websocket doesn't have on_shutdown callback. – Sergei Struk Nov 14 '15 at 18:38
  • 1
    @SergeiStruk - I'm sorry the `at_exit` didn't work... Another option is to catch the signal before the exit process starts, do something and than forward it. I edited my answer, please have a look. – Myst Nov 14 '15 at 19:12