Packages
livebook
0.19.4
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_runtime_component.ex
defmodule LivebookWeb.SessionLive.AttachedRuntimeComponent do
use LivebookWeb, :live_component
import Ecto.Changeset
@impl true
def mount(socket) do
unless Livebook.Config.runtime_enabled?(Livebook.Runtime.Attached) do
raise "runtime module not allowed"
end
{:ok, socket}
end
@impl true
def update(assigns, socket) do
changeset =
case socket.assigns[:changeset] do
nil ->
changeset(assigns.runtime)
changeset when socket.assigns.runtime == assigns.runtime ->
changeset
changeset ->
changeset(assigns.runtime, changeset.params)
end
socket =
socket
|> assign(assigns)
|> assign(:changeset, changeset)
{:ok, socket}
end
defp changeset(runtime, attrs \\ %{}) do
data =
case runtime do
%Livebook.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">
<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 Elixir {Livebook.Runtime.Attached.elixir_version_requirement()}.
Make sure to give the node a name and a cookie, for example:
</p>
<div class="text-gray-700 markdown">
<pre><code>iex --name {test_node()} --cookie mycookie -S mix</code></pre>
</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"
phx-target={@myself}
autocomplete="off"
spellcheck="false"
>
<div class="flex flex-col space-y-4 mb-6">
<.text_field field={f[:name]} label="Name" placeholder={test_node()} />
<.text_field field={f[:cookie]} label="Cookie" placeholder="mycookie" />
</div>
<.button type="submit" disabled={@runtime_status == :connecting or not @changeset.valid?}>
{label(@changeset, @runtime_status)}
</.button>
</.form>
</div>
"""
end
defp label(changeset, runtime_status) do
reconnecting? = changeset.valid? and changeset.data == apply_changes(changeset)
case {reconnecting?, runtime_status} do
{true, :connected} -> "Reconnect"
{true, :connecting} -> "Connecting..."
_ -> "Connect"
end
end
@impl true
def handle_event("validate", %{"data" => data}, socket) do
changeset =
socket.assigns.runtime
|> changeset(data)
|> Map.replace!(:action, :validate)
{:noreply, assign(socket, changeset: changeset)}
end
def handle_event("init", %{"data" => data}, socket) do
socket.assigns.runtime
|> changeset(data)
|> apply_action(:insert)
|> case do
{:ok, data} ->
node = String.to_atom(data.name)
cookie = String.to_atom(data.cookie)
runtime = Livebook.Runtime.Attached.new(node, cookie)
Livebook.Session.set_runtime(socket.assigns.session.pid, runtime)
Livebook.Session.connect_runtime(socket.assigns.session.pid)
{:noreply, socket}
{:error, changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
defp test_node() do
"test@#{Livebook.Utils.node_host()}"
end
end