Packages
livebook
0.12.0
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Current section
Files
Jump to
Current section
Files
lib/livebook_web/live/session_live/attached_live.ex
defmodule LivebookWeb.SessionLive.AttachedLive do
use LivebookWeb, :live_view
import Ecto.Changeset
alias Livebook.{Session, Runtime}
@impl true
def mount(
_params,
%{"session_pid" => session_pid, "current_runtime" => current_runtime},
socket
) do
session = Session.get_by_pid(session_pid)
unless Livebook.Config.runtime_enabled?(Livebook.Runtime.Attached) do
raise "runtime module not allowed"
end
if connected?(socket) do
Session.subscribe(session.id)
end
{:ok,
assign(socket,
session: session,
current_runtime: current_runtime,
error_message: nil,
changeset: changeset(current_runtime)
)}
end
defp changeset(runtime, attrs \\ %{}) do
data =
case runtime do
%Runtime.Attached{node: node, cookie: cookie} ->
%{name: Atom.to_string(node), cookie: Atom.to_string(cookie)}
_ ->
%{name: nil, cookie: nil}
end
types = %{name: :string, cookie: :string}
cast({data, types}, attrs, [:name, :cookie])
|> validate_required([:name, :cookie])
end
@impl true
def render(assigns) do
~H"""
<div class="flex-col space-y-5">
<div :if={@error_message} class="error-box">
<%= @error_message %>
</div>
<p class="text-gray-700">
Connect the session to an already running node
and evaluate code in the context of that node.
The node must run Erlang/OTP <%= :erlang.system_info(:otp_release) %> and Elixir <%= System.version() %> (or later).
Make sure to give the node a name and a cookie, for example:
</p>
<div class="text-gray-700 markdown">
<%= if longname = Livebook.Config.longname() do %>
<pre><code>iex --name test@<%= longname %> --cookie mycookie -S mix</code></pre>
<% else %>
<pre><code>iex --sname test --cookie mycookie -S mix</code></pre>
<% end %>
</div>
<p class="text-gray-700">
Then enter the connection information below:
</p>
<.form
:let={f}
for={@changeset}
as={:data}
phx-submit="init"
phx-change="validate"
autocomplete="off"
spellcheck="false"
>
<div class="flex flex-col space-y-4">
<.text_field field={f[:name]} label="Name" placeholder={name_placeholder()} />
<.text_field field={f[:cookie]} label="Cookie" placeholder="mycookie" />
</div>
<button class="mt-5 button-base button-blue" type="submit" disabled={not @changeset.valid?}>
<%= if(reconnecting?(@changeset), do: "Reconnect", else: "Connect") %>
</button>
</.form>
</div>
"""
end
@impl true
def handle_event("validate", %{"data" => data}, socket) do
changeset =
socket.assigns.current_runtime |> changeset(data) |> Map.replace!(:action, :validate)
{:noreply, assign(socket, changeset: changeset)}
end
def handle_event("init", %{"data" => data}, socket) do
socket.assigns.current_runtime
|> changeset(data)
|> apply_action(:insert)
|> case do
{:ok, data} ->
node = String.to_atom(data.name)
cookie = String.to_atom(data.cookie)
runtime = Runtime.Attached.new(node, cookie)
case Runtime.connect(runtime) do
{:ok, runtime} ->
Session.set_runtime(socket.assigns.session.pid, runtime)
{:noreply, assign(socket, changeset: changeset(runtime), error_message: nil)}
{:error, message} ->
{:noreply,
assign(socket,
changeset: changeset(socket.assigns.current_runtime, data),
error_message: Livebook.Utils.upcase_first(message)
)}
end
{:error, changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
@impl true
def handle_info({:operation, {:set_runtime, _pid, runtime}}, socket) do
{:noreply, assign(socket, current_runtime: runtime)}
end
def handle_info(_message, socket), do: {:noreply, socket}
defp reconnecting?(changeset) do
changeset.valid? and changeset.data == apply_changes(changeset)
end
defp name_placeholder do
if longname = Livebook.Config.longname(), do: "test@#{longname}", else: "test"
end
end