phoenix_gen_socket_client icon indicating copy to clipboard operation
phoenix_gen_socket_client copied to clipboard

Handling WebSocket Timeouts and Reconnection in this client

Open alexaung98 opened this issue 1 year ago • 7 comments

WebSocket timeout and phoenix_gen_socket_client are not reconnecting to the WebSocket server.

I added a timeout behavior to my server WebSocket in endpoint.ex:

socket "/socket", MyWeb.UserSocket, websocket: [timeout: 30_000], longpoll: false

Expectation

When the server closes the connection, the client should automatically reconnect to the server.

Behavior

The client does not detect that the server has closed the connection and remains in the joined state. As a result, when the server sends a message to the client, the client does not actually receive it.

alexaung98 avatar May 24 '24 03:05 alexaung98

This was easily can fix regarding this below documentation.

https://hexdocs.pm/phoenix_gen_socket_client/Phoenix.Channels.GenSocketClient.Transport.WebSocketClient.html

So I will close this issue here.

alexaung98 avatar May 24 '24 04:05 alexaung98

WebSocket timeout and phoenix_gen_socket_client are not reconnecting to the WebSocket server.

I added a timeout behavior to my server WebSocket in endpoint.ex:

socket "/socket", MyWeb.UserSocket, websocket: [timeout: 30_000], longpoll: false

Expectation

When the server closes the connection, the client should automatically reconnect to the server.

Behavior

The client does not detect that the server has closed the connection and remains in the joined state. As a result, when the server sends a message to the client, the client does not actually receive it.

I am having the same issue.

I am using phoenix_gen_socket_client for client side and phoenix/channels for server side. I am facing an issue with {:shutdown, :closed}, my server close the channel if he didn't receive any data during 60s. For simulation purpose I set keepalive time for 120s in my client side. The issue is once server close the channel it suppose to receive handle_channel_closed callback. But it doesn't.

aungmyooo2k17 avatar Jun 12 '24 03:06 aungmyooo2k17

This was easily can fix regarding this below documentation.

https://hexdocs.pm/phoenix_gen_socket_client/Phoenix.Channels.GenSocketClient.Transport.WebSocketClient.html

So I will close this issue here.

This one also no help

alexaung98 avatar Jun 12 '24 03:06 alexaung98

I'm facing a problem that could be rooted into what has been described in this issue.

I checked the underlying websocket_client erlang library that is being used by this dep. for the keepalive and these are being sent correctly.

What I noticed though is that if for any reason a keepalive message is not reaching the server before the timeout period, the server will kill the socket process. The client using the phoenix_gen_socket_client will never get notified (no callback is invoked on the client side).

If the client tries to send a new message, a reconnection is automatically triggered If the server is broadcasting a message to the topic the client is supposed to be listening to, the client does not receive anything

My assumption is that the keepalive mechanism within the websocket_client is not bubbling up the connection status to this library so it can invoke a callback and let us define how to handle this case...

For now I can think of two workarounds:

  1. Reduce the keepalive to 20 seconds (that way if one keepalive message doesn't reach the server, there's still a second chance before the timeout fires)
  2. Implement a heartbeat mechanism within the client, by sending this message a reconnection to the socket will be automatically triggered if it has been dropped by the server, in that case you can disable the keepalive mechanism

ℹ to pass params to the websocket library you need to pass the socket_opts inside atransport_opts field

start_link(
  __MODULE__, # callback :: [module]
  Phoenix.Channels.GenSocketClient.Transport.WebSocketClient, # transport_mod :: [module]
  _, # [any]
  [transport_opts: [keepalive: 20_000]], #[socket_opts]
  name: my_name, #[GenServer.options]
)

There is a typo in doc here: https://hexdocs.pm/phoenix_gen_socket_client/Phoenix.Channels.GenSocketClient.Transport.WebSocketClient.html#content

Set the keepalive value to nil WILL disable the keepalive mechanism

💡 Ideally, the "supposedly" erroring keepalives should trigger a new callback

jfayad avatar Jul 06 '25 08:07 jfayad

Related to #73

J0 avatar Aug 03 '25 12:08 J0

Related to #73

I do confirm, that my investigations led me to a debugging script that looked like that (inside web_socket_client.ex)

def websocket_info({:tcp_closed, frame} = reason, req, state) do
    dbg()
    GenSocketClient.notify_disconnected(state.socket, reason)
    {:close, reason, frame, :normal, state}
  end

which was being triggered during the silent disconnection phase.

The PR seems to be a solid fix for that, I'll test and report back if these still occur

jfayad avatar Aug 04 '25 06:08 jfayad

Thanks for circling back, I’ll likely queue a release tomorrow after some testing on my end as well.

J0 avatar Aug 05 '25 16:08 J0