Save notebook and notify clients when session is stopped (#45)

This commit is contained in:
Jonatan Kłosko 2021-02-21 19:17:14 +01:00 committed by GitHub
parent 0925ec77cd
commit c1eafc9a2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 6 deletions

View file

@ -215,11 +215,14 @@ defmodule LiveBook.Session do
end
@doc """
Synchronously stops the server.
Asynchronously sends a close request to the server.
This results in saving the file and broadcasting
a :closed message to the session topic.
"""
@spec stop(id()) :: :ok
def stop(session_id) do
GenServer.stop(name(session_id))
@spec close(id()) :: :ok
def close(session_id) do
GenServer.cast(name(session_id), :close)
end
## Callbacks
@ -377,6 +380,13 @@ defmodule LiveBook.Session do
{:noreply, maybe_save_notebook(state)}
end
def handle_cast(:close, state) do
maybe_save_notebook(state)
broadcast_message(state.session_id, :session_closed)
{:stop, :shutdown, state}
end
@impl true
def handle_info({:DOWN, ref, :process, _, _}, %{runtime_monitor_ref: ref} = state) do
broadcast_info(state.session_id, "runtime node terminated unexpectedly")

View file

@ -50,13 +50,13 @@ defmodule LiveBook.SessionSupervisor do
end
@doc """
Synchronously stops a session process identified by the given id.
Asynchronously stops a session process identified by the given id.
Broadcasts `{:session_delete, id}` message under the `"sessions"` topic.
"""
@spec delete_session(Session.id()) :: :ok
def delete_session(id) do
Session.stop(id)
Session.close(id)
broadcast_sessions_message({:session_deleted, id})
:ok
end

View file

@ -382,6 +382,13 @@ defmodule LiveBookWeb.SessionLive do
{:noreply, put_flash(socket, :info, message)}
end
def handle_info(:session_closed, socket) do
{:noreply,
socket
|> put_flash(:info, "Session has been closed")
|> push_redirect(to: Routes.home_path(socket, :page))}
end
def handle_info(_message, socket), do: {:noreply, socket}
defp after_operation(socket, _prev_socket, {:insert_section, _index, section_id}) do

View file

@ -23,9 +23,11 @@ defmodule LiveBook.SessionSupervisorTest do
test "stops the session process identified by the given id" do
{:ok, id} = SessionSupervisor.create_session()
{:ok, pid} = SessionSupervisor.get_session_pid(id)
ref = Process.monitor(pid)
SessionSupervisor.delete_session(id)
assert_receive {:DOWN, ^ref, :process, _, _}
refute has_child_with_pid?(SessionSupervisor, pid)
end

View file

@ -187,6 +187,28 @@ defmodule LiveBook.SessionTest do
end
end
describe "close/1" do
@tag :tmp_dir
test "saves the notebook and notifies subscribers once the session is closed",
%{session_id: session_id, tmp_dir: tmp_dir} do
path = Path.join(tmp_dir, "notebook.livemd")
Session.set_path(session_id, path)
# Perform a change, so the notebook is dirty
Session.set_notebook_name(session_id, "My notebook")
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
refute File.exists?(path)
Process.flag(:trap_exit, true)
Session.close(session_id)
assert_receive :session_closed
assert File.exists?(path)
assert File.read!(path) =~ "My notebook"
end
end
describe "start_link/1" do
@tag :tmp_dir
test "fails if the given path is already in use", %{tmp_dir: tmp_dir} do