Teams Server
Mix.install([
{:phoenix_playground, "~> 0.1.7"},
{:kino, "~> 0.15.3"},
{:livebook_proto,
github: "hugobarauna/livebook-notebooks", sparse: "talks/alchemyconf/livebook_proto"},
])
require Logger
Server
defmodule UserSocket do
@behaviour Phoenix.Socket.Transport
@impl true
def child_spec(_opts) do
# We won't spawn any process, so let's ignore the child spec
:ignore
end
@impl true
def connect(%{connect_info: %{x_headers: x_headers}}) do
org_name = get_header(x_headers, "x-org-name")
Logger.debug("[SERVER] Received WebSocket connection with org name: #{org_name}")
{:ok, %{org_name: org_name}}
end
@impl true
def init(state) do
Phoenix.PubSub.subscribe(PhoenixPlayground.PubSub, "org_events:#{state.org_name}")
message = build_client_connected_message(state.org_name)
send(self(), {:message, message})
{:ok, state}
end
defp build_client_connected_message(_org_name) do
env_var = %LivebookProto.EnvironmentVariable{name: "API_TOKEN", value: "some api token"}
client_connected = %LivebookProto.ClientConnected{env_vars: [env_var]}
event = %LivebookProto.Event{type: {:client_connected, client_connected}}
LivebookProto.Event.encode(event)
end
@impl true
def handle_info({:message, message}, state) do
Logger.debug("[SERVER] Sending WebSocket message to client: #{inspect(message)}")
{:push, {:binary, message}, state}
end
@impl true
def handle_in({_message, _opts}, state) do
{:ok, state}
end
@impl true
def terminate(_reason, _state) do
:ok
end
defp get_header(headers, key) do
for {^key, value} <- headers, do: value
end
end
defmodule Teams.Endpoint do
use Phoenix.Endpoint, otp_app: :phoenix_playground
socket("/user", UserSocket, websocket: [connect_info: [:x_headers]])
end
{:ok, phx_playground_pid} =
PhoenixPlayground.start(endpoint: Teams.Endpoint, port: 4701, open_browser: false)
import Kino.Shorts
build_event = fn :env_var_created, env_var ->
env_var = %LivebookProto.EnvironmentVariable{name: env_var.name, value: env_var.value}
env_var_created = %LivebookProto.EnvironmentVariableCreated{env_var: env_var}
event = %LivebookProto.Event{type: {:env_var_created, env_var_created}}
LivebookProto.Event.encode(event)
end
feedback_frame = Kino.Frame.new(placeholder: false)
form =
Kino.Control.form(
[
org_name: Kino.Input.text("Org name", default: "dashbit"),
name: Kino.Input.text("Name"),
value: Kino.Input.text("Value")
],
submit: "Create"
)
Kino.listen(form, fn form_event ->
%{data: %{org_name: org_name, name: name, value: value}} = form_event
Kino.Frame.render(feedback_frame, Kino.Text.new("env var created", style: [color: :green]))
message = build_event.(:env_var_created, %{name: name, value: value})
Phoenix.PubSub.broadcast!(
PhoenixPlayground.PubSub,
"org_events:#{org_name}",
{:message, message}
)
end)
grid([markdown("### New env var"), feedback_frame, form], boxed: true)