Created
October 10, 2020 12:19
-
-
Save dealloc/cae812882ca8501e223531e2516e2572 to your computer and use it in GitHub Desktop.
Echo socket demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PooledConnWeb.Socket.EchoSocket do | |
@moduledoc """ | |
Javascript code to run this (put in .html.eex file): | |
const id = <%= :rand.uniform(10) %>; | |
const websocket = new WebSocket('ws://localhost:4000/socket/websocket?id=' + id); | |
websocket.onopen = (args) => console.info('Open', args); | |
websocket.onmessage = (msg, args) => console.info('Message', msg, args); | |
websocket.onclose = (args) => console.warn('Close', args); | |
""" | |
@behaviour Phoenix.Socket.Transport | |
require Logger | |
def child_spec(_opts) do | |
%{id: Task, start: {Task, :start_link, [fn -> :ok end]}, restart: :transient} | |
end | |
# This gets called on connection, but does NOT run in the process of the socket yet! | |
def connect(map) do | |
{:ok, map} | |
end | |
# This gets called after connecting, and runs INSIDE process of the socket, register your socket in here! | |
def init(%{params: %{"id" => id}} = state) do | |
# Right now I just get the ID of a socket from the query parameters, but you can obviously use whatever logic you want. | |
Registry.register(SocketRegistry, id, nil) | |
# For simplicity I just store the ID of this socket as the state, again use whatever suits your needs here. | |
{:ok, id} | |
end | |
# This is called for incoming SOCKET messages (aka anything sent over the websocket). | |
def handle_in({text, _opts}, state) do | |
# Here text is the ID of the socket I want to sent to (see the demo javascript), and I send "Hello from <id of this websocket here>" to the other socket | |
case Registry.lookup(SocketRegistry, text) do | |
[] -> | |
raise "Could not find #{text}" | |
[{pid, _meta}] -> | |
# This will send an ERLANG message to the other socket, and invokes handle_info | |
send(pid, "Hello from #{state}") | |
end | |
{:reply, :ok, {:text, text}, state} | |
end | |
# This gets invoked when send/3 is called by the other socket. | |
# Basically you can send whatever you want, just make sure to return {:push, {:text, "message here"}, state} which will return the message to the client. | |
def handle_info(msg, state) do | |
Logger.info("handle_info##{state}: #{inspect(msg)}") | |
{:push, {:text, "handle_info: #{msg}"}, state} | |
end | |
def terminate(reason, _state) do | |
Logger.info("terminate: #{inspect(reason)}") | |
:ok | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment