You need to assign an ID to every socket that corresponds to a particular user. Then you can do this:
MyAppWeb.Endpoint.broadcast(socket_id, "disconnect", %{})
To assign the ID to the socket, find the module where you do this:
use Absinthe.Phoenix.Socket,
schema: MyAppWeb.Schema
It is probably in lib/my_app_web/channels/user_socket.ex
.
In that “socket” module, you write your ID callbacks like this:
@impl true
def id(%{
assigns: %{
absinthe: %{
opts: [
context: %{current_user: current_user}
]
}
}
}),
do: socket_id_for_user(current_user)
def id(_socket), do: nil
def socket_id_for_user(%{id: id}), do: "user_socket:#{id}"
Now you just have to make sure this current_user
assign is on your socket.
First, go to your router and put this line in any pipelines that need it (usually just the :api
pipeline, sometimes the :browser
pipeline):
plug :fetch_current_user
In your router (or in an imported module, whichever you prefer), write this function:
def fetch_current_user(conn, _opts) do
# I don't know how you do auth so get your user your own way.
# For me, it usually involves finding their session token in the DB.
user = get_user_from_conn(conn)
context = if is_nil(user), do: %{}, else: %{current_user: user}
conn
|> Absinthe.Plug.assign_context(context)
end
You may want to do other stuff in this function.
If you use phx_gen_auth
you are probably putting the user_token in private assigns, for example.
The main problem you have now is that if you are sending your log-out mutation over this socket, you will have closed it before you can send a response. Very fun problem.