Show reconnect button when connecting to a matching runtime (#113)

* Show reconnect button when connecting to a matching runtime

* Add runtime config test
This commit is contained in:
Jonatan Kłosko 2021-03-23 19:41:03 +01:00 committed by GitHub
parent a18122cfcb
commit 50db813092
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 24 deletions

View file

@ -4,8 +4,12 @@ defmodule LivebookWeb.SessionLive.ElixirStandaloneLive do
alias Livebook.{Session, Runtime}
@impl true
def mount(_params, %{"session_id" => session_id}, socket) do
{:ok, assign(socket, session_id: session_id, output: nil)}
def mount(_params, %{"session_id" => session_id, "current_runtime" => current_runtime}, socket) do
if connected?(socket) do
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
end
{:ok, assign(socket, session_id: session_id, output: nil, current_runtime: current_runtime)}
end
@impl true
@ -18,7 +22,7 @@ defmodule LivebookWeb.SessionLive.ElixirStandaloneLive do
as soon as you evaluate the first cell.
</p>
<button class="button button-primary" phx-click="init">
Connect
<%= if(matching_runtime?(@current_runtime), do: "Reconnect", else: "Connect") %>
</button>
<%= if @output do %>
<div class="markdown max-h-20 overflow-y-auto tiny-scrollbar">
@ -29,10 +33,21 @@ defmodule LivebookWeb.SessionLive.ElixirStandaloneLive do
"""
end
defp matching_runtime?(%Runtime.ElixirStandalone{}), do: true
defp matching_runtime?(_runtime), do: false
@impl true
def handle_event("init", _params, socket) do
{:ok, runtime} = Runtime.ElixirStandalone.init()
Session.connect_runtime(socket.assigns.session_id, runtime)
{:noreply, socket}
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}
end

View file

@ -7,11 +7,16 @@ defmodule LivebookWeb.SessionLive.MixStandaloneLive do
@impl true
def mount(_params, %{"session_id" => session_id, "current_runtime" => current_runtime}, socket) do
if connected?(socket) do
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
end
{:ok,
assign(socket,
session_id: session_id,
status: :initial,
path: if(current_runtime, do: current_runtime.project_path, else: default_path()),
current_runtime: current_runtime,
path: initial_path(current_runtime),
outputs: [],
emitter: nil
), temporary_assigns: [outputs: []]}
@ -35,7 +40,10 @@ defmodule LivebookWeb.SessionLive.MixStandaloneLive do
running_paths: [],
target: nil %>
</div>
<%= content_tag :button, "Connect", class: "button button-primary", phx_click: "init", disabled: not mix_project_root?(@path) %>
<%= content_tag :button, if(matching_runtime?(@current_runtime, @path), do: "Reconnect", else: "Connect"),
class: "button button-primary",
phx_click: "init",
disabled: not mix_project_root?(@path) %>
<% end %>
<%= if @status != :initial do %>
<div class="markdown">
@ -50,6 +58,12 @@ defmodule LivebookWeb.SessionLive.MixStandaloneLive do
"""
end
defp matching_runtime?(%Runtime.MixStandalone{} = runtime, path) do
Path.expand(runtime.project_path) == Path.expand(path)
end
defp matching_runtime?(_runtime, _path), do: false
@impl true
def handle_event("set_path", %{"path" => path}, socket) do
{:noreply, assign(socket, path: path)}
@ -76,13 +90,21 @@ defmodule LivebookWeb.SessionLive.MixStandaloneLive do
end
end
def handle_info({:operation, {:set_runtime, _pid, runtime}}, socket) do
{:noreply, assign(socket, current_runtime: runtime)}
end
def handle_info(_, socket), do: {:noreply, socket}
defp add_output(socket, output) do
assign(socket, outputs: socket.assigns.outputs ++ [{output, Utils.random_id()}])
end
defp default_path(), do: File.cwd!() <> "/"
defp initial_path(%Runtime.MixStandalone{} = current_runtime) do
current_runtime.project_path
end
defp initial_path(_runtime), do: File.cwd!() <> "/"
defp mix_project_root?(path) do
File.dir?(path) and File.exists?(Path.join(path, "mix.exs"))

View file

@ -86,23 +86,17 @@ defmodule LivebookWeb.SessionLive.RuntimeComponent do
<%= if @type == "elixir_standalone" do %>
<%= live_render @socket, LivebookWeb.SessionLive.ElixirStandaloneLive,
id: :elixir_standalone_runtime,
session: %{"session_id" => @session_id} %>
session: %{"session_id" => @session_id, "current_runtime" => @runtime} %>
<% end %>
<%= if @type == "mix_standalone" do %>
<%= live_render @socket, LivebookWeb.SessionLive.MixStandaloneLive,
id: :mix_standalone_runtime,
session: %{
"session_id" => @session_id,
"current_runtime" => if_matches_type(@runtime, @type)
} %>
session: %{"session_id" => @session_id, "current_runtime" => @runtime} %>
<% end %>
<%= if @type == "attached" do %>
<%= live_render @socket, LivebookWeb.SessionLive.AttachedLive,
id: :attached_runtime,
session: %{
"session_id" => @session_id,
"current_runtime" => if_matches_type(@runtime, @type)
} %>
session: %{"session_id" => @session_id, "current_runtime" => @runtime} %>
<% end %>
</div>
</div>
@ -113,14 +107,6 @@ defmodule LivebookWeb.SessionLive.RuntimeComponent do
defp runtime_type_label(%Runtime.MixStandalone{}), do: "Mix standalone"
defp runtime_type_label(%Runtime.Attached{}), do: "Attached"
def if_matches_type(runtime, type) do
if runtime && runtime_type(runtime) == type do
runtime
else
nil
end
end
defp runtime_type(%Runtime.ElixirStandalone{}), do: "elixir_standalone"
defp runtime_type(%Runtime.MixStandalone{}), do: "mix_standalone"
defp runtime_type(%Runtime.Attached{}), do: "attached"

View file

@ -3,7 +3,7 @@ defmodule LivebookWeb.SessionLiveTest do
import Phoenix.LiveViewTest
alias Livebook.{SessionSupervisor, Session, Delta}
alias Livebook.{SessionSupervisor, Session, Delta, Runtime}
setup do
{:ok, session_id} = SessionSupervisor.create_session()
@ -166,6 +166,30 @@ defmodule LivebookWeb.SessionLiveTest do
end
end
describe "runtime settings" do
test "connecting to elixir standalone updates connect button to reconnect",
%{conn: conn, session_id: session_id} do
{:ok, view, _} = live(conn, "/sessions/#{session_id}/settings/runtime")
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
[elixir_standalone_view] = live_children(view)
elixir_standalone_view
|> element("button", "Connect")
|> render_click()
assert_receive {:operation, {:set_runtime, _pid, %Runtime.ElixirStandalone{} = runtime}}
page = render(view)
assert page =~ Atom.to_string(runtime.node)
assert page =~ "Reconnect"
assert page =~ "Disconnect"
end
end
# Helpers
defp wait_for_session_update(session_id) do
# This call is synchronous, so it gives the session time
# for handling the previously sent change messages.