From fc6652ea8892f43b7355ae7ce265d1740213e614 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Wed, 1 Apr 2020 15:41:38 +0200 Subject: [PATCH] =?UTF-8?q?=E2=98=81=20More=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Pluto.jl | 11 ++- src/{react => notebookserver}/Cell.jl | 0 src/notebookserver/Client.jl | 66 +++++++++++++++ .../FormatOutput.jl | 0 src/{react => notebookserver}/Notebook.jl | 0 src/react/WorkspaceManager.jl | 2 +- src/webserver/Dynamic.jl | 84 ++++--------------- .../{NotebookServer.jl => WebServer.jl} | 17 ++-- 8 files changed, 94 insertions(+), 86 deletions(-) rename src/{react => notebookserver}/Cell.jl (100%) create mode 100644 src/notebookserver/Client.jl rename src/{webserver => notebookserver}/FormatOutput.jl (100%) rename src/{react => notebookserver}/Notebook.jl (100%) rename src/webserver/{NotebookServer.jl => WebServer.jl} (96%) diff --git a/src/Pluto.jl b/src/Pluto.jl index 461e2c7a63..33bc499981 100644 --- a/src/Pluto.jl +++ b/src/Pluto.jl @@ -16,16 +16,19 @@ const PLUTO_VERSION_STR = 'v' * string(PLUTO_VERSION) include("./react/ExploreExpression.jl") using .ExploreExpression -include("./webserver/FormatOutput.jl") -include("./react/Cell.jl") -include("./react/Notebook.jl") +include("./notebookserver/FormatOutput.jl") +include("./notebookserver/Cell.jl") +include("./notebookserver/Notebook.jl") +include("./notebookserver/Client.jl") + + include("./react/WorkspaceManager.jl") include("./react/Errors.jl") include("./react/React.jl") include("./react/Run.jl") -include("./webserver/NotebookServer.jl") +include("./webserver/WebServer.jl") include("./webserver/Static.jl") include("./webserver/Dynamic.jl") diff --git a/src/react/Cell.jl b/src/notebookserver/Cell.jl similarity index 100% rename from src/react/Cell.jl rename to src/notebookserver/Cell.jl diff --git a/src/notebookserver/Client.jl b/src/notebookserver/Client.jl new file mode 100644 index 0000000000..d83e7474c5 --- /dev/null +++ b/src/notebookserver/Client.jl @@ -0,0 +1,66 @@ +mutable struct Client + id::Symbol + stream::Any + connected_notebook::Union{Notebook,Nothing} + pendingupdates::Channel +end + +Client(id::Symbol, stream) = Client(id, stream, nothing, Channel(128)) + + +struct UpdateMessage + type::Symbol + message::Any + notebook::Union{Notebook,Nothing} + cell::Union{Cell,Nothing} + initiator::Union{Client,Nothing} +end + +UpdateMessage(type::Symbol, message::Any) = UpdateMessage(type, message, nothing, nothing, nothing) +UpdateMessage(type::Symbol, message::Any, notebook::Notebook) = UpdateMessage(type, message, notebook, nothing, nothing) + + +function clientupdate_cell_output(initiator::Client, notebook::Notebook, cell::Cell) + payload, mime = cell.output_repr, cell.repr_mime + + return UpdateMessage(:cell_output, + Dict(:mime => mime, + :output => payload, + :errormessage => cell.error_repr, + :runtime => cell.runtime, + ), + notebook, cell, initiator) +end + +function clientupdate_cell_input(initiator::Client, notebook::Notebook, cell::Cell) + return UpdateMessage(:cell_input, + Dict(:code => cell.code), notebook, cell, initiator) +end + +function clientupdate_cell_added(initiator::Client, notebook::Notebook, cell::Cell, new_index::Integer) + return UpdateMessage(:cell_added, + Dict(:index => new_index - 1, # 1-based index (julia) to 0-based index (js) + ), notebook, cell, initiator) +end + +function clientupdate_cell_deleted(initiator::Client, notebook::Notebook, cell::Cell) + return UpdateMessage(:cell_deleted, + Dict(), notebook, cell, initiator) +end + +function clientupdate_cell_moved(initiator::Client, notebook::Notebook, cell::Cell, new_index::Integer) + return UpdateMessage(:cell_moved, + Dict(:index => new_index - 1, # 1-based index (julia) to 0-based index (js) + ), notebook, cell, initiator) +end + +function clientupdate_cell_dependecies(initiator::Client, notebook::Notebook, cell::Cell, dependentcells) + return UpdateMessage(:cell_dependecies, + Dict(:depenentcells => [string(c.uuid) for c in dependentcells], + ), notebook, cell, initiator) +end + +function clientupdate_cell_running(initiator::Client, notebook::Notebook, cell::Cell) + return UpdateMessage(:cell_running, + Dict(), notebook, cell, initiator) +end \ No newline at end of file diff --git a/src/webserver/FormatOutput.jl b/src/notebookserver/FormatOutput.jl similarity index 100% rename from src/webserver/FormatOutput.jl rename to src/notebookserver/FormatOutput.jl diff --git a/src/react/Notebook.jl b/src/notebookserver/Notebook.jl similarity index 100% rename from src/react/Notebook.jl rename to src/notebookserver/Notebook.jl diff --git a/src/react/WorkspaceManager.jl b/src/react/WorkspaceManager.jl index e0774aacc8..83eefc4fcd 100644 --- a/src/react/WorkspaceManager.jl +++ b/src/react/WorkspaceManager.jl @@ -69,7 +69,7 @@ function make_workspace(notebook::Notebook, ::Val{ProcessWorkspace})::ProcessWor eval_in_workspace.([workspace], workspace_preamble) # TODO: we could also import Pluto - eval_in_workspace(workspace, :(include($(joinpath(PKG_ROOT_DIR, "src", "webserver", "FormatOutput.jl"))))) + eval_in_workspace(workspace, :(include($(joinpath(PKG_ROOT_DIR, "src", "notebookserver", "FormatOutput.jl"))))) workspace end diff --git a/src/webserver/Dynamic.jl b/src/webserver/Dynamic.jl index a1ce632ff8..fabea59a7f 100644 --- a/src/webserver/Dynamic.jl +++ b/src/webserver/Dynamic.jl @@ -4,17 +4,6 @@ import JSON import JSON: lower JSON.lower(m::MIME) = string(m) -struct UpdateMessage - type::Symbol - message::Any - notebook::Union{Notebook,Nothing} - cell::Union{Cell,Nothing} - initiator::Union{Client,Nothing} -end - -UpdateMessage(type::Symbol, message::Any) = UpdateMessage(type, message, nothing, nothing, nothing) -UpdateMessage(type::Symbol, message::Any, notebook::Notebook) = UpdateMessage(type, message, notebook, nothing, nothing) - function serialize_message_to_stream(io::IO, message::UpdateMessage) to_send = Dict(:type => message.type, :message => message.message) if message.notebook !== nothing @@ -35,52 +24,9 @@ function serialize_message(message::UpdateMessage) end -function clientupdate_cell_output(initiator::Client, notebook::Notebook, cell::Cell) - payload, mime = cell.output_repr, cell.repr_mime - - return UpdateMessage(:cell_output, - Dict(:mime => mime, - :output => payload, - :errormessage => cell.error_repr, - :runtime => cell.runtime, - ), - notebook, cell, initiator) -end - -function clientupdate_cell_input(initiator::Client, notebook::Notebook, cell::Cell) - return UpdateMessage(:cell_input, - Dict(:code => cell.code), notebook, cell, initiator) -end - -function clientupdate_cell_added(initiator::Client, notebook::Notebook, cell::Cell, new_index::Integer) - return UpdateMessage(:cell_added, - Dict(:index => new_index - 1, # 1-based index (julia) to 0-based index (js) - ), notebook, cell, initiator) -end - -function clientupdate_cell_deleted(initiator::Client, notebook::Notebook, cell::Cell) - return UpdateMessage(:cell_deleted, - Dict(), notebook, cell, initiator) -end -function clientupdate_cell_moved(initiator::Client, notebook::Notebook, cell::Cell, new_index::Integer) - return UpdateMessage(:cell_moved, - Dict(:index => new_index - 1, # 1-based index (julia) to 0-based index (js) - ), notebook, cell, initiator) -end - -function clientupdate_cell_dependecies(initiator::Client, notebook::Notebook, cell::Cell, dependentcells) - return UpdateMessage(:cell_dependecies, - Dict(:depenentcells => [string(c.uuid) for c in dependentcells], - ), notebook, cell, initiator) -end -function clientupdate_cell_running(initiator::Client, notebook::Notebook, cell::Cell) - return UpdateMessage(:cell_running, - Dict(), notebook, cell, initiator) -end - -"To be used in `make_distinct!`" +"To be used in `make_paths_distinct!`" mutable struct NotebookPath uuid path_split @@ -106,7 +52,7 @@ For example, the set will become `/a/b/c.jl`, `P/c.jl`, `/Q/b/c.jl`, 'R.jl'""" -function make_distinct!(notebookpaths::Set{NotebookPath}) +function make_paths_distinct!(notebookpaths::Set{NotebookPath}) counts = count_occurances(np.current_path for np in notebookpaths) for (current_path, count) in counts if count == 1 && !isempty(current_path) @@ -129,7 +75,7 @@ function make_distinct!(notebookpaths::Set{NotebookPath}) end end - make_distinct!(not_yet_distinct) + make_paths_distinct!(not_yet_distinct) end end end @@ -146,7 +92,7 @@ function clientupdate_notebook_list(initiator::Client, notebook_list) NotebookPath(notebook.uuid, path_split, "", -1) end - make_distinct!(Set(notebookpaths)) + make_paths_distinct!(Set(notebookpaths)) short_paths = Dict(map(notebookpaths) do np np.uuid => np.current_path @@ -161,9 +107,7 @@ function clientupdate_notebook_list(initiator::Client, notebook_list) end - - -function handle_changecell(initiator, notebook, cell, newcode) +function handle_changecell(initiator::Client, notebook, cell, newcode) # i.e. Ctrl+Enter was pressed on this cell # we update our `Notebook` and start execution @@ -178,13 +122,13 @@ function handle_changecell(initiator, notebook, cell, newcode) putnotebookupdates!(notebook, clientupdate_cell_input(initiator, notebook, cell)) - to_update = run_reactive_async!(initiator, notebook, cell) + run_reactive_async!(initiator, notebook, cell) end # TODO: actions on the notebook are not thread safe -addresponse(:addcell) do (initiator, body, notebook) +responses[:addcell] = (initiator::Client, body, notebook::Notebook) -> begin new_index = body["index"] + 1 # 0-based index (js) to 1-based index (julia) new_cell = Cell("") @@ -195,7 +139,7 @@ addresponse(:addcell) do (initiator, body, notebook) nothing end -addresponse(:deletecell) do (initiator, body, notebook, cell) +responses[:deletecell] = (initiator::Client, body, notebook::Notebook, cell::Cell) -> begin to_delete = cell changecell_succes = handle_changecell(initiator, notebook, to_delete, "") @@ -206,7 +150,7 @@ addresponse(:deletecell) do (initiator, body, notebook, cell) nothing end -addresponse(:movecell) do (initiator, body, notebook, cell) +responses[:movecell] = (initiator::Client, body, notebook::Notebook, cell::Cell) -> begin to_move = cell # Indexing works as if a new cell is added. @@ -229,23 +173,23 @@ addresponse(:movecell) do (initiator, body, notebook, cell) nothing end -addresponse(:changecell) do (initiator, body, notebook, cell) +responses[:changecell] = (initiator::Client, body, notebook::Notebook, cell::Cell) -> begin newcode = body["code"] handle_changecell(initiator, notebook, cell, newcode) nothing end -addresponse(:runall) do (initiator, body, notebook) +responses[:runall] = (initiator::Client, body, notebook::Notebook) -> begin to_update = run_reactive_async!(initiator, notebook, notebook.cells) end # TODO: -# addresponse(:getcell) do (initiator, body, notebook, cell) +# responses[:getcell] = (initiator, body, notebook::Notebook, cell::Cell) -> begin # end -addresponse(:getallcells) do (initiator, body, notebook) +responses[:getallcells] = (initiator::Client, body, notebook::Notebook) -> begin # TODO: updates = [] for (i, cell) in enumerate(notebook.cells) @@ -259,7 +203,7 @@ addresponse(:getallcells) do (initiator, body, notebook) nothing end -addresponse(:getallnotebooks) do (initiator, body) +responses[:getallnotebooks] = (initiator::Client, body, notebook=nothing) -> begin putplutoupdates!(clientupdate_notebook_list(initiator, values(notebooks))) nothing end \ No newline at end of file diff --git a/src/webserver/NotebookServer.jl b/src/webserver/WebServer.jl similarity index 96% rename from src/webserver/NotebookServer.jl rename to src/webserver/WebServer.jl index b89edaa475..c85e5fa921 100644 --- a/src/webserver/NotebookServer.jl +++ b/src/webserver/WebServer.jl @@ -3,15 +3,6 @@ import UUIDs: UUID import HTTP import Sockets -mutable struct Client - id::Symbol - stream::Any - connected_notebook::Union{Notebook,Nothing} - pendingupdates::Channel -end - -Client(id::Symbol, stream) = Client(id, stream, nothing, Channel(128)) - connectedclients = Dict{Symbol,Client}() notebooks = Dict{UUID,Notebook}() @@ -96,7 +87,6 @@ end "Will hold all 'response handlers': functions that respond to a WebSocket request from the client. These are defined in `src/webserver/Dynamic.jl`." responses = Dict{Symbol,Function}() -addresponse(f::Function, endpoint::Symbol) = responses[endpoint] = f """Start a Pluto server _synchronously_ (i.e. blocking call) on `http://localhost:[port]/`. @@ -167,7 +157,12 @@ function run(port = 1234, launchbrowser = false) if haskey(responses, messagetype) responsefunc = responses[messagetype] - responsefunc((client, body, args...)) + try + responsefunc(client, body, args...) + catch ex + @warn "Response function to message of type $(messagetype) failed" + rethrow(ex) + end else @warn "Message of type $(messagetype) not recognised" end