Skip to content

Commit

Permalink
πŸ’πŸ“© Support publish_to_js inside logs (#2607)
Browse files Browse the repository at this point in the history
  • Loading branch information
fonsp authored Jul 17, 2023
1 parent f76efd4 commit c569adf
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 22 deletions.
4 changes: 3 additions & 1 deletion frontend/components/Cell.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,9 @@ export const Cell = ({
set_cm_highlighted_line=${set_cm_highlighted_line}
onerror=${remount}
/>
${show_logs ? html`<${Logs} logs=${Object.values(logs)} line_heights=${line_heights} set_cm_highlighted_line=${set_cm_highlighted_line} />` : null}
${show_logs && cell_api_ready
? html`<${Logs} logs=${Object.values(logs)} line_heights=${line_heights} set_cm_highlighted_line=${set_cm_highlighted_line} />`
: null}
<${RunArea}
cell_id=${cell_id}
running_disabled=${running_disabled}
Expand Down
4 changes: 4 additions & 0 deletions src/evaluation/WorkspaceManager.jl
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@ function start_relaying_logs((session, notebook)::SN, log_channel::Distributed.R

@assert !isnothing(display_cell)

# this handles the use of published_to_js inside logs: objects that were newly published during the rendering of the log args.
merge!(display_cell.published_objects, next_log["new_published_objects"])
delete!(next_log, "new_published_objects")

push!(display_cell.logs, next_log)
Pluto.@asynclog update_throttled()
catch e
Expand Down
50 changes: 33 additions & 17 deletions src/runner/PlutoRunner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2125,28 +2125,26 @@ end"""
"""
const currently_running_cell_id = Ref{UUID}(uuid4())

function _publish(x, id_start)::String
assertpackable(x)

id = string(notebook_id[], "/", currently_running_cell_id[], "/", id_start)
d = get!(Dict{String,Any}, cell_published_objects, currently_running_cell_id[])
function _publish(x, id_start, cell_id)::String
id = "$(notebook_id[])/$cell_id/$id_start"
d = get!(Dict{String,Any}, cell_published_objects, cell_id)
d[id] = x
return id
end

_publish(x) = _publish(x, objectid2str(x))

# TODO? Possibly move this to it's own package, with fallback that actually msgpack?
# ..... Ideally we'd make this require `await` on the javascript side too...
Base.@kwdef struct PublishedToJavascript
published_id
published_object
published_id_start
cell_id
end
function Base.show(io::IO, ::MIME"text/javascript", published::PublishedToJavascript)
if published.cell_id != currently_running_cell_id[]
error("Showing result from PlutoRunner.publish_to_js() in a cell different from where it was created, not (yet?) supported.")
end
write(io, "/* See the documentation for PlutoRunner.publish_to_js */ getPublishedObject(\"$(published.published_id)\")")
id = _publish(published.published_object, published.published_id_start, published.cell_id)
# if published.cell_id != currently_running_cell_id[]
# error("Showing result from PlutoRunner.publish_to_js() in a cell different from where it was created, not (yet?) supported.")
# end
write(io, "/* See the documentation for PlutoRunner.publish_to_js */ getPublishedObject(\"$(id)\")")
end
Base.show(io::IO, ::MIME"text/plain", published::PublishedToJavascript) = show(io, MIME("text/javascript"), published)
Base.show(io::IO, published::PublishedToJavascript) = show(io, MIME("text/javascript"), published)
Expand Down Expand Up @@ -2179,9 +2177,13 @@ let
end
```
"""
function publish_to_js(args...)
publish_to_js(x) = publish_to_js(x, objectid2str(x))

function publish_to_js(x, id_start)
assertpackable(x)
PublishedToJavascript(
published_id=_publish(args...),
published_object=x,
published_id_start=id_start,
cell_id=currently_running_cell_id[],
)
end
Expand Down Expand Up @@ -2387,18 +2389,32 @@ function Logging.handle_message(pl::PlutoCellLogger, level, msg, _module, group,
end

try

yield()

po() = get(cell_published_objects, pl.cell_id, Dict{String,Any}())
before_published_object_keys = collect(keys(po()))

# Render the log arguments:
msg_formatted = format_output_default(msg isa AbstractString ? Text(msg) : msg)
kwargs_formatted = Tuple{String,Any}[(string(k), format_log_value(v)) for (k, v) in kwargs if k != :maxlog]

after_published_object_keys = collect(keys(po()))
new_published_object_keys = setdiff(after_published_object_keys, before_published_object_keys)

# (Running `put!(pl.log_channel, x)` will send `x` to the pluto server. See `start_relaying_logs` for the receiving end.)
put!(pl.log_channel, Dict{String,Any}(
"level" => string(level),
"msg" => format_output_default(msg isa AbstractString ? Text(msg) : msg),
"msg" => msg_formatted,
# This is a dictionary containing all published objects that were published during the rendering of the log arguments (we cannot track which objects were published during the execution of the log statement itself i think...)
"new_published_objects" => Dict{String,Any}(
key => po()[key] for key in new_published_object_keys
),
"group" => string(group),
"id" => string(id),
"file" => string(file),
"cell_id" => pl.cell_id,
"line" => line isa Union{Int32,Int64} ? line : nothing,
"kwargs" => Tuple{String,Any}[(string(k), format_log_value(v)) for (k, v) in kwargs if k != :maxlog],
"kwargs" => kwargs_formatted,
))

yield()
Expand Down
2 changes: 1 addition & 1 deletion src/webserver/Dynamic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function notebook_to_js(notebook::Notebook)
"cell_id" => cell.cell_id,
"depends_on_disabled_cells" => cell.depends_on_disabled_cells,
"output" => FirebaseyUtils.ImmutableMarker(cell.output),
"published_object_keys" => keys(cell.published_objects),
"published_object_keys" => collect(keys(cell.published_objects)),
"queued" => cell.queued,
"running" => cell.running,
"errored" => cell.errored,
Expand Down
8 changes: 5 additions & 3 deletions test/Dynamic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,19 @@ end
@testset "PlutoRunner API" begin
🍭 = ServerSession()
🍭.options.evaluation.workspace_use_distributed = true

cid = uuid1()

notebook = Notebook([
Cell("PlutoRunner.notebook_id[] |> Text"),
Cell("""
Cell(cid, """
let
# not actually public API but we test it anyways
a = PlutoRunner._publish(Dict(
"hello" => "world",
"xx" => UInt8[6,7,8],
))
b = PlutoRunner._publish("cool")
), "aaa", Base.UUID("$cid"))
b = PlutoRunner._publish("cool", "bbb", Base.UUID("$cid"))
Text((a, b))
end
"""),
Expand Down

0 comments on commit c569adf

Please sign in to comment.