Packages
kino
0.15.2
0.19.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.3
0.15.2
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.2
0.6.1
0.6.0
retired
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Interactive widgets for Livebook
Current section
Files
Jump to
Current section
Files
lib/kino/js/data_store.ex
defmodule Kino.JS.DataStore do
@moduledoc false
# Process responsible for keeping the data for static JS outputs.
# Unlike JS.Live kinos, plain JS kinos have no server, so we use
# a single process for storing their data and replying to data
# queries.
use GenServer
@name __MODULE__
def cross_node_name() do
{@name, node()}
end
@doc """
Starts the data store.
"""
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, {}, name: @name)
end
@doc """
Stores output data under the given ref.
"""
@spec store(Kino.Output.ref(), term(), function()) :: :ok
def store(ref, data, export) do
GenServer.cast(@name, {:store, ref, data, export})
end
@impl true
def init({}) do
{:ok, %{ref_with_data: %{}}}
end
@impl true
def handle_cast({:store, ref, data, export}, state) do
state = put_in(state.ref_with_data[ref], %{data: data, export: export, export_result: nil})
{:noreply, state}
end
@impl true
def handle_info({:connect, pid, %{origin: _origin, ref: ref}}, state) do
with {:ok, %{data: data}} <- Map.fetch(state.ref_with_data, ref) do
Kino.Bridge.send(pid, {:connect_reply, data, %{ref: ref}})
end
{:noreply, state}
end
def handle_info({:export, pid, %{ref: ref}}, state) do
case state.ref_with_data do
%{^ref => info} ->
{state, export_result} =
if info.export_result do
{state, info.export_result}
else
export_result = info.export.(info.data)
state = put_in(state.ref_with_data[ref].export_result, export_result)
{state, export_result}
end
Kino.Bridge.send(pid, {:export_reply, export_result, %{ref: ref}})
{:noreply, state}
_ ->
{:noreply, state}
end
end
def handle_info({:remove, ref}, state) do
{_, state} = pop_in(state.ref_with_data[ref])
{:noreply, state}
end
end