Packages
livebook
0.8.1
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
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/livebook/runtime/attached.ex
defmodule Livebook.Runtime.Attached do
@moduledoc false
# A runtime backed by an Elixir node managed externally.
#
# Such node must be already started and available, Livebook doesn't
# manage its lifetime in any way and only loads/unloads the
# necessary elements. The node can be an ordinary Elixir runtime,
# a Mix project shell, a running release or anything else.
defstruct [:node, :cookie, :server_pid]
@type t :: %__MODULE__{
node: node(),
cookie: atom(),
server_pid: pid() | nil
}
@doc """
Returns a new runtime instance.
"""
@spec new(node(), atom()) :: t()
def new(node, cookie \\ Node.get_cookie()) do
%__MODULE__{node: node, cookie: cookie}
end
@doc """
Checks if the given node is available for use and initializes
it with Livebook-specific modules and processes.
"""
@spec connect(t()) :: {:ok, t()} | {:error, String.t()}
def connect(runtime) do
%{node: node, cookie: cookie} = runtime
# We need to append the hostname on connect because
# net_kernel has not yet started during new/2.
node = append_hostname(node)
# Set cookie for connecting to this specific node
Node.set_cookie(node, cookie)
case Node.ping(node) do
:pong ->
server_pid =
Livebook.Runtime.ErlDist.initialize(node,
node_manager_opts: [parent_node: node(), capture_orphan_logs: false]
)
{:ok, %{runtime | node: node, server_pid: server_pid}}
:pang ->
{:error, "node #{inspect(node)} is unreachable"}
end
end
defp append_hostname(node) do
with :nomatch <- :string.find(Atom.to_string(node), "@"),
<<suffix::binary>> <- :string.find(Atom.to_string(:net_kernel.nodename()), "@") do
:"#{node}#{suffix}"
else
_ -> node
end
end
end
defimpl Livebook.Runtime, for: Livebook.Runtime.Attached do
alias Livebook.Runtime.ErlDist.RuntimeServer
def describe(runtime) do
[
{"Type", "Attached"},
{"Node name", Atom.to_string(runtime.node)}
]
end
def connect(runtime) do
Livebook.Runtime.Attached.connect(runtime)
end
def connected?(runtime) do
runtime.server_pid != nil
end
def take_ownership(runtime, opts \\ []) do
RuntimeServer.attach(runtime.server_pid, self(), opts)
Process.monitor(runtime.server_pid)
end
def disconnect(runtime) do
RuntimeServer.stop(runtime.server_pid)
{:ok, %{runtime | server_pid: nil}}
end
def duplicate(runtime) do
Livebook.Runtime.Attached.new(runtime.node, runtime.cookie)
end
def evaluate_code(runtime, code, locator, parent_locators, opts \\ []) do
RuntimeServer.evaluate_code(runtime.server_pid, code, locator, parent_locators, opts)
end
def forget_evaluation(runtime, locator) do
RuntimeServer.forget_evaluation(runtime.server_pid, locator)
end
def drop_container(runtime, container_ref) do
RuntimeServer.drop_container(runtime.server_pid, container_ref)
end
def handle_intellisense(runtime, send_to, request, parent_locators) do
RuntimeServer.handle_intellisense(runtime.server_pid, send_to, request, parent_locators)
end
def read_file(runtime, path) do
RuntimeServer.read_file(runtime.server_pid, path)
end
def transfer_file(runtime, path, file_id, callback) do
RuntimeServer.transfer_file(runtime.server_pid, path, file_id, callback)
end
def revoke_file(runtime, file_id) do
RuntimeServer.revoke_file(runtime.server_pid, file_id)
end
def start_smart_cell(runtime, kind, ref, attrs, parent_locators) do
RuntimeServer.start_smart_cell(runtime.server_pid, kind, ref, attrs, parent_locators)
end
def set_smart_cell_parent_locators(runtime, ref, parent_locators) do
RuntimeServer.set_smart_cell_parent_locators(runtime.server_pid, ref, parent_locators)
end
def stop_smart_cell(runtime, ref) do
RuntimeServer.stop_smart_cell(runtime.server_pid, ref)
end
def fixed_dependencies?(_runtime), do: true
def add_dependencies(_runtime, _code, _dependencies) do
raise "not supported"
end
def search_packages(_runtime, _send_to, _search) do
raise "not supported"
end
def disable_dependencies_cache(runtime) do
RuntimeServer.disable_dependencies_cache(runtime.server_pid)
end
def put_system_envs(runtime, envs) do
RuntimeServer.put_system_envs(runtime.server_pid, envs)
end
def delete_system_envs(runtime, names) do
RuntimeServer.delete_system_envs(runtime.server_pid, names)
end
end