Add an option to run setup with no cache (#1616)

This commit is contained in:
Jonatan Kłosko 2023-01-03 12:24:22 +01:00 committed by GitHub
parent 1a895e4b29
commit 2e230c9deb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 149 additions and 17 deletions

View file

@ -233,6 +233,16 @@
@apply bottom-0 left-0 transform translate-y-full -mb-1;
}
.menu__content--top-left.menu__content--distant,
.menu__content--top-right.menu__content--distant {
@apply -mt-2;
}
.menu__content--bottom-left.menu__content--distant,
.menu__content--bottom-right.menu__content--distant {
@apply -mb-2;
}
.menu:not(.menu--open) > .menu__overlay,
.menu:not(.menu--open) > .menu__content {
@apply hidden;

View file

@ -526,7 +526,10 @@ const Session = {
);
if (evalButton) {
const cellId = evalButton.getAttribute("data-cell-id");
this.queueCellEvaluation(cellId);
const disableDependenciesCache = evalButton.hasAttribute(
"data-disable-dependencies-cache"
);
this.queueCellEvaluation(cellId, disableDependenciesCache);
}
const hash = window.location.hash;
@ -740,9 +743,12 @@ const Session = {
}
},
queueCellEvaluation(cellId) {
queueCellEvaluation(cellId, disableDependenciesCache) {
this.dispatchQueueEvaluation(() => {
this.pushEvent("queue_cell_evaluation", { cell_id: cellId });
this.pushEvent("queue_cell_evaluation", {
cell_id: cellId,
disable_dependencies_cache: disableDependenciesCache,
});
});
},

View file

@ -504,6 +504,13 @@ defprotocol Livebook.Runtime do
@spec search_packages(t(), pid(), String.t()) :: reference()
def search_packages(runtime, send_to, search)
@doc """
Disables dependencies cache, so they are fetched and compiled from
scratch.
"""
@spec disable_dependencies_cache(t()) :: :ok
def disable_dependencies_cache(runtime)
@doc """
Sets the given environment variables.
"""

View file

@ -137,6 +137,10 @@ defimpl Livebook.Runtime, for: Livebook.Runtime.Attached 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

View file

@ -300,6 +300,10 @@ defimpl Livebook.Runtime, for: Livebook.Runtime.ElixirStandalone do
Livebook.Runtime.Dependencies.search_packages_on_hex(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

View file

@ -122,6 +122,10 @@ defimpl Livebook.Runtime, for: Livebook.Runtime.Embedded do
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

View file

@ -180,6 +180,14 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do
GenServer.cast(pid, {:stop_smart_cell, ref})
end
@doc """
Disables dependencies cache globally.
"""
@spec disable_dependencies_cache(pid()) :: :ok
def disable_dependencies_cache(pid) do
GenServer.cast(pid, :disable_dependencies_cache)
end
@doc """
Sets the given environment variables.
"""
@ -497,6 +505,12 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do
{:noreply, state}
end
def handle_cast(:disable_dependencies_cache, state) do
System.put_env("MIX_INSTALL_FORCE", "true")
{:noreply, state}
end
def handle_cast({:put_system_envs, envs}, state) do
envs
|> Enum.map(fn

View file

@ -361,6 +361,14 @@ defmodule Livebook.Session do
GenServer.cast(pid, {:add_dependencies, dependencies})
end
@doc """
Sends disable dependencies cache request to the server.
"""
@spec disable_dependencies_cache(pid()) :: :ok
def disable_dependencies_cache(pid) do
GenServer.cast(pid, :disable_dependencies_cache)
end
@doc """
Sends cell evaluation request to the server.
"""
@ -854,6 +862,14 @@ defmodule Livebook.Session do
{:noreply, do_add_dependencies(state, dependencies)}
end
def handle_cast(:disable_dependencies_cache, state) do
if Runtime.connected?(state.data.runtime) do
Runtime.disable_dependencies_cache(state.data.runtime)
end
{:noreply, state}
end
def handle_cast({:queue_cell_evaluation, client_pid, cell_id}, state) do
client_id = client_id(state, client_pid)
operation = {:queue_cells_evaluation, client_id, [cell_id]}

View file

@ -447,6 +447,9 @@ defmodule LivebookWeb.LiveHelpers do
* `:position` - which side of the clickable the menu menu should
be attached to, either `"left"` or `"right"`. Defaults to `"right"`
* `:distant` - whether the menu should be further from the anchor
element. Defaults to `false`
* `:secondary_click` - whether secondary click (usually right mouse click)
should open the menu. Defaults to `false`
@ -466,6 +469,7 @@ defmodule LivebookWeb.LiveHelpers do
assigns
|> assign_new(:disabled, fn -> false end)
|> assign_new(:position, fn -> "bottom-right" end)
|> assign_new(:distant, fn -> false end)
|> assign_new(:secondary_click, fn -> false end)
~H"""
@ -480,7 +484,7 @@ defmodule LivebookWeb.LiveHelpers do
</div>
<div class="menu__overlay" phx-click-away={JS.remove_class("menu--open", to: "##{@id}")}></div>
<menu
class={"menu__content #{menu_content_class(@position)}"}
class={"menu__content #{menu_content_class(@position)} #{if(@distant, do: "menu__content--distant")}"}
role="menu"
phx-click-away={JS.remove_class("menu--open", to: "##{@id}")}
>

View file

@ -1144,7 +1144,7 @@ defmodule LivebookWeb.SessionLive do
{:noreply, socket}
end
def handle_event("queue_cell_evaluation", %{"cell_id" => cell_id}, socket) do
def handle_event("queue_cell_evaluation", %{"cell_id" => cell_id} = params, socket) do
assert_policy!(socket, :execute)
data = socket.private.data
@ -1157,6 +1157,10 @@ defmodule LivebookWeb.SessionLive do
_ -> {:ok, socket}
end
if params["disable_dependencies_cache"] do
Session.disable_dependencies_cache(socket.assigns.session.pid)
end
if status == :ok do
Session.queue_cell_evaluation(socket.assigns.session.pid, cell_id)
end

View file

@ -112,6 +112,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do
cell_id={@cell_view.id}
validity={@cell_view.eval.validity}
status={@cell_view.eval.status}
runtime={@runtime}
/>
</:primary>
<:secondary>
@ -339,19 +340,42 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp setup_cell_evaluation_button(%{status: :ready} = assigns) do
~H"""
<button
class="text-gray-600 hover:text-gray-800 focus:text-gray-800 flex space-x-1 items-center"
data-el-queue-cell-evaluation-button
data-cell-id={@cell_id}
>
<%= if @validity == :fresh do %>
<.remix_icon icon="play-circle-fill" class="text-xl" />
<span class="text-sm font-medium">Setup</span>
<% else %>
<.remix_icon icon="restart-fill" class="text-xl" />
<span class="text-sm font-medium">Reconnect and setup</span>
<div class="flex items-center space-x-1">
<button
class="text-gray-600 hover:text-gray-800 focus:text-gray-800 flex space-x-1 items-center"
data-el-queue-cell-evaluation-button
data-cell-id={@cell_id}
>
<%= if @validity == :fresh do %>
<.remix_icon icon="play-circle-fill" class="text-xl" />
<span class="text-sm font-medium">Setup</span>
<% else %>
<.remix_icon icon="restart-fill" class="text-xl" />
<span class="text-sm font-medium">Reconnect and setup</span>
<% end %>
</button>
<%= unless Livebook.Runtime.fixed_dependencies?(@runtime) do %>
<.menu id="setup-menu" position="bottom-left" distant>
<:toggle>
<button class="flex text-gray-600 hover:text-gray-800 focus:text-gray-800">
<.remix_icon icon="arrow-down-s-line" class="text-xl" />
</button>
</:toggle>
<:content>
<button
class="menu-item text-gray-500"
role="menuitem"
data-el-queue-cell-evaluation-button
data-cell-id={@cell_id}
data-disable-dependencies-cache
>
<.remix_icon icon="play-circle-fill" />
<span class="font-medium">Setup without cache</span>
</button>
</:content>
</.menu>
<% end %>
</button>
</div>
"""
end

View file

@ -143,6 +143,39 @@ defmodule LivebookWeb.SessionLiveTest do
assert_receive {:operation, {:set_runtime, _pid, %{} = _runtime}}
end
test "reevaluting the setup cell with dependencies cache disabled",
%{conn: conn, session: session} do
Session.subscribe(session.id)
# Start the standalone runtime, to encapsulate env var changes
{:ok, runtime} = Runtime.ElixirStandalone.new() |> Runtime.connect()
Session.set_runtime(session.pid, runtime)
evaluate_setup(session.pid)
{:ok, view, _} = live(conn, "/sessions/#{session.id}")
view
|> element(~s{[data-el-session]})
|> render_hook("queue_cell_evaluation", %{
"cell_id" => "setup",
"disable_dependencies_cache" => true
})
section_id = insert_section(session.pid)
cell_id =
insert_text_cell(session.pid, section_id, :code, ~s/System.get_env("MIX_INSTALL_FORCE")/)
view
|> element(~s{[data-el-session]})
|> render_hook("queue_cell_evaluation", %{"cell_id" => cell_id})
assert_receive {:operation,
{:add_cell_evaluation_response, _, ^cell_id, {:text, "\e[32m\"true\"\e[0m"},
_}}
end
test "cancelling cell evaluation", %{conn: conn, session: session} do
section_id = insert_section(session.pid)
cell_id = insert_text_cell(session.pid, section_id, :code, "Process.sleep(2000)")

View file

@ -39,6 +39,8 @@ defmodule Livebook.Runtime.NoopRuntime do
def search_packages(_, _, _), do: make_ref()
def disable_dependencies_cache(_), do: :ok
def put_system_envs(_, _), do: :ok
def delete_system_envs(_, _), do: :ok
end