livebook/lib/livebook/runtime/embedded.ex
2024-05-24 14:27:38 +02:00

181 lines
5.2 KiB
Elixir

defmodule Livebook.Runtime.Embedded do
# A runtime backed by the same node Livebook is running in.
#
# This runtime is reserved for specific use cases, where there is
# no option of starting a separate Elixir runtime.
defstruct [:server_pid]
@type t :: %__MODULE__{server_pid: pid() | nil}
alias Livebook.Runtime.ErlDist
@doc """
Returns a new runtime instance.
"""
@spec new() :: t()
def new() do
%__MODULE__{}
end
@doc """
Initializes new runtime by starting the necessary processes within
the current node.
"""
@spec connect(t()) :: {:ok, t()}
def connect(runtime) do
# As we run in the Livebook node, all the necessary modules
# are in place, so we just start the manager process.
# We make it anonymous, so that multiple embedded runtimes
# can be started (for different notebooks).
# We also disable cleanup, as we don't want to unload any
# modules or revert the configuration (because other runtimes
# may rely on it). If someone uses embedded runtimes,
# this cleanup is not particularly important anyway.
# We tell manager to not override :standard_error,
# as we already do it for the Livebook application globally
# (see Livebook.Application.start/2).
server_pid =
ErlDist.initialize(node(),
node_manager_opts: [unload_modules_on_termination: false]
)
{:ok, %{runtime | server_pid: server_pid}}
end
end
defimpl Livebook.Runtime, for: Livebook.Runtime.Embedded do
alias Livebook.Runtime.ErlDist.RuntimeServer
def describe(_runtime) do
[{"Type", "Embedded"}]
end
def connect(runtime) do
Livebook.Runtime.Embedded.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.Embedded.new()
end
def evaluate_code(runtime, language, code, locator, parent_locators, opts \\ []) do
RuntimeServer.evaluate_code(
runtime.server_pid,
language,
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, node) do
RuntimeServer.handle_intellisense(runtime.server_pid, send_to, request, parent_locators, node)
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 relabel_file(runtime, file_id, new_file_id) do
RuntimeServer.relabel_file(runtime.server_pid, file_id, new_file_id)
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
not Keyword.has_key?(config(), :load_packages)
end
def add_dependencies(_runtime, code, dependencies) do
Livebook.Runtime.Dependencies.add_dependencies(code, dependencies)
end
def has_dependencies?(runtime, dependencies) do
RuntimeServer.has_dependencies?(runtime.server_pid, dependencies)
end
def snippet_definitions(_runtime) do
Livebook.Runtime.Definitions.snippet_definitions()
end
def search_packages(_runtime, send_to, search) do
{mod, fun, args} = config()[:load_packages]
packages = apply(mod, fun, args)
Livebook.Runtime.Dependencies.search_packages_in_list(packages, send_to, search)
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
def restore_transient_state(runtime, transient_state) do
RuntimeServer.restore_transient_state(runtime.server_pid, transient_state)
end
def register_clients(runtime, clients) do
RuntimeServer.register_clients(runtime.server_pid, clients)
end
def unregister_clients(runtime, client_ids) do
RuntimeServer.unregister_clients(runtime.server_pid, client_ids)
end
def fetch_proxy_handler(runtime, client_pid) do
RuntimeServer.fetch_proxy_handler(runtime.server_pid, client_pid)
end
defp config() do
Application.get_env(:livebook, Livebook.Runtime.Embedded, [])
end
end