In my application, clients establish a websocket connection to a phoenix channel. After some actions, the server needs to close the connection
Right now in order to accomplish this I do in my service module:
MyApp.Endpoint.broadcast("topic", "end_session", %{})
In channel:
def handle_info("end_session", _params, socket) do
Logger.debug("Ending session...")
push socket, "end_session", %{}
{:stop, :normal, socket}
end
def terminate(reason, _socket) do
Logger.debug"Terminating socket... #{inspect reason}"
:ok
end
and in the socket.js:
channel.on("end_session", payload => {
console.log("terminating session")
channel.leave()
})
channel.onClose( () => console.log("channel has been closed") )
I’m wondering if this is the proper way to gracefully terminate the channel from the server side?
Thanks!
4 Likes
There is a disconnect event described in user_socket.ex.
# Socket id's are topics that allow you to identify all sockets for a given user:
#
# def id(socket), do: "user_socket:#{socket.assigns.user_id}"
#
# Would allow you to broadcast a "disconnect" event and terminate
# all active sockets and channels for a given user:
#
# BlahWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
#
# Returning `nil` makes this socket anonymous.
Never used it, but it might be what You are looking for.
1 Like
I tried that approach (broadcasting the disconnect
event) and it works from the server side of things.
The problem is that the front-end can’t tell whether it should try to reconnect or not, because the wasClean
attribute of the close
event is sometimes false
and sometimes true
. I was expecting it to be always true
in that case. Am I wrong?
I’m on Phoenix 1.7.9
What I usually do is send a “kicked” message to the front end before closing the channel. That way the front end can stop reconnecting or often redirect to the login page.
2 Likes