If you configure a WebSocket like shown below, where is the state for that WebSocket held? What object represents the WebSocket? How can you invoke its functions for that connection?
The given simple demo Hex WebSocket code is:
Mix.install([:bandit, :websock_adapter])
defmodule EchoServer do
def init(options) do
{:ok, options}
end
def handle_in({"ping", [opcode: :text]}, state) do
{:reply, :ok, {:text, "pong"}, state}
end
def terminate(:timeout, state) do
{:ok, state}
end
end
defmodule Router do
use Plug.Router
plug Plug.Logger
plug :match
plug :dispatch
get "/" do
send_resp(conn, 200, """
Use the JavaScript console to interact using websockets
sock = new WebSocket("ws://localhost:4000/websocket")
sock.addEventListener("message", console.log)
sock.addEventListener("open", () => sock.send("ping"))
""")
end
get "/websocket" do
conn
|> WebSockAdapter.upgrade(EchoServer, [], timeout: 60_000)
|> halt()
end
match _ do
send_resp(conn, 404, "not found")
end
end
require Logger
webserver = {Bandit, plug: Router, scheme: :http, port: 4000}
{:ok, _} = Supervisor.start_link([webserver], strategy: :one_for_one)
Logger.info("Plug now running on localhost:4000")
Process.sleep(:infinity)
I assumed from that code that EchoServer
is the object containing the state of the websocket connection, and thus one EchoServer
is made per connected client. And you will just need a reference to that EchoServer
to invoke its functions (somehow). But I was told this is not the case.
Somewhere the WebSocket must be managed and represented with state and as an object. So where is it if not there?
Or is it the conn
which holds the connection state (and is upgraded to include EchoServer functions)? Is it conn
’s PID we need then to keep? And if so, can we invoke its EchoServer
functions after it is upgraded to this?
handle_in
takes state
as an argument, so is this not representing a GenServer-like unit with its own state?
I wrote a longer question along these lines here but perhaps that was too verbose. The question really just boils down to which class contains the socket and how to invoke its functions externally on demand (eg. like sending the user a text message through the socket). Thanks for any help.