pejrich
How to list all the connected sockets, or to track them
I’m developing an app, and I think my client is creating too many socket/channel connection, so I decided to setup some watchers. I followed Chris McCord’s code in this SO post: https://stackoverflow.com/questions/33934029/how-to-detect-if-a-user-left-a-phoenix-channel-due-to-a-network-disconnect
I created both a ChannelWatcher, and a SocketWatcher. The ChannelWatcher is working as I would expect, however the SocketWatcher is a bit weird, the pid that connects to the socket seems to die shortly after connecting (even though from the client side, the socket is still connected).
@impl true
def connect(%{"token" => token}, socket, _connect_info) do
case Authentication.resource_from_access_token(token) do
{:ok, user} ->
SocketWatcher.monitor(self(), {__MODULE__, :on_disconnect, [user.id]})
{:ok, Phoenix.Socket.assign(socket, current_user: user)}
_ ->
:error
end
end
...
def on_disconnect(pid) do
IO.puts("#{pid}'s socket disconnected")
end
However the PID seems to die immediately
SocketWatcher monitoring #PID<0.3054.0> <- Logged from the SocketWatcher.monitor function
:ok
[debug] CONNECTED TO MyAppWeb.UserSocket in 3ms
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"token" => "ACCESS_TOKEN", "vsn" => "2.0.0"}
#PID<0.3054.0>'s socket disconnected <- Logged from UserSocket's on_disconnect function
Perhaps I misunderstand how Sockets work, but I thought it was a long-lasting PID that holds the connection. How do I find where the Sockets are listed? Are they stored in an ETS table? Can I watch them like I would a channel’s PID?
Most Liked
pejrich
It’s the other way around, channel connections happen over a single socket. This is why my issue is not with the channels, but with the socket.
For example, if I did this on the client:
let socket1 = ...
socket1.connect();
let socket2 = ...
socket2.connect();
let socket3 = ...
socket3.connect();
let channel = socket3.channel("room:lobby", {})
channel.join();
If I only track Presence in the Channel.join, then the above code would appear to have 1 socket, with 1 channel, but it actually has 1 socket with 1 channel, and 2 sockets with 0 channels.
I’ve found a solution though,
defmodule MyAppWeb.UserSocket do
@impl true
def init({_, socket} = state) do
SocketWatcher.monitor(
self(),
{__MODULE__, :on_disconnect, [socket.assigns.current_user.id]}
)
Phoenix.Socket.__init__(state)
end
use Phoenix.Socket
...
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance










