Support optional reevaluation on smart cell update (#1062)

This commit is contained in:
Jonatan Kłosko 2022-03-18 19:36:48 +01:00 committed by GitHub
parent ee1ea91e19
commit becdda61f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 6 deletions

View file

@ -933,11 +933,11 @@ defmodule Livebook.Session do
end
end
def handle_info({:runtime_smart_cell_update, id, attrs, source}, state) do
def handle_info({:runtime_smart_cell_update, id, attrs, source, info}, state) do
case Notebook.fetch_cell_and_section(state.data.notebook, id) do
{:ok, cell, _section} ->
delta = Livebook.JSInterop.diff(cell.source, source)
operation = {:update_smart_cell, self(), id, attrs, delta}
operation = {:update_smart_cell, self(), id, attrs, delta, info.reevaluate}
{:noreply, handle_operation(state, operation)}
:error ->

View file

@ -167,7 +167,8 @@ defmodule Livebook.Session.Data do
| {:cancel_cell_evaluation, pid(), Cell.id()}
| {:smart_cell_started, pid(), Cell.id(), Delta.t(), Runtime.js_view(),
Cell.Smart.editor() | nil}
| {:update_smart_cell, pid(), Cell.id(), Cell.Smart.attrs(), Delta.t()}
| {:update_smart_cell, pid(), Cell.id(), Cell.Smart.attrs(), Delta.t(),
reevaluate :: boolean()}
| {:erase_outputs, pid()}
| {:set_notebook_name, pid(), String.t()}
| {:set_section_name, pid(), Section.id(), String.t()}
@ -558,12 +559,13 @@ defmodule Livebook.Session.Data do
end
end
def apply_operation(data, {:update_smart_cell, client_pid, id, attrs, delta}) do
with {:ok, %Cell.Smart{} = cell, _section} <-
def apply_operation(data, {:update_smart_cell, client_pid, id, attrs, delta, reevaluate}) do
with {:ok, %Cell.Smart{} = cell, section} <-
Notebook.fetch_cell_and_section(data.notebook, id) do
data
|> with_actions()
|> update_smart_cell(cell, client_pid, attrs, delta)
|> maybe_queue_updated_smart_cell(cell, section, reevaluate)
|> set_dirty()
|> wrap_ok()
else
@ -1251,6 +1253,21 @@ defmodule Livebook.Session.Data do
|> add_action({:broadcast_delta, client_pid, updated_cell, :primary, delta})
end
defp maybe_queue_updated_smart_cell({data, _} = data_actions, cell, section, reevaluate) do
info = data.cell_infos[cell.id]
evaluated? = info.eval.status == :ready and info.eval.validity in [:evaluated, :stale]
if evaluated? and reevaluate do
data_actions
|> queue_prerequisite_cells_evaluation(cell)
|> queue_cell_evaluation(cell, section)
|> maybe_evaluate_queued()
else
data_actions
end
end
defp erase_outputs({data, _} = data_actions) do
data_actions
|> clear_all_evaluation()

View file

@ -2748,7 +2748,7 @@ defmodule Livebook.Session.DataTest do
attrs = %{"text" => "content!"}
delta2 = Delta.new() |> Delta.retain(7) |> Delta.insert("!")
operation = {:update_smart_cell, client_pid, "c1", attrs, delta2}
operation = {:update_smart_cell, client_pid, "c1", attrs, delta2, false}
assert {:ok,
%{
@ -2759,6 +2759,28 @@ defmodule Livebook.Session.DataTest do
[{:broadcast_delta, ^client_pid, _cell, :primary, ^delta2}]} =
Data.apply_operation(data, operation)
end
test "queues the cell when already evaluated and reevaluate is specified" do
client_pid = self()
data =
data_after_operations!([
{:insert_section, self(), 0, "s1"},
{:set_runtime, self(), NoopRuntime.new()},
{:set_smart_cell_definitions, self(), [%{kind: "text", name: "Text"}]},
{:insert_cell, self(), "s1", 0, :smart, "c1", %{kind: "text"}},
{:smart_cell_started, self(), "c1", Delta.new(), %{}, nil},
{:queue_cells_evaluation, self(), ["c1"]},
{:add_cell_evaluation_response, self(), "c1", @eval_resp, @eval_meta}
])
operation = {:update_smart_cell, client_pid, "c1", %{}, Delta.new(), true}
assert {:ok,
%{
cell_infos: %{"c1" => %{eval: %{status: :evaluating}}}
}, _actions} = Data.apply_operation(data, operation)
end
end
describe "apply_operation/2 given :erase_outputs" do