Race condition when delaying Kino.JS.Live.call reply
jannikbecher opened this issue · comments
When creating a new kino and directly invoking a call with a delayed response the following error occurs:
** (exit) exited in: GenServer.call(#PID<0.757.0>, :test, 5000)
** (EXIT) time out
(elixir 1.15.7) lib/gen_server.ex:1074: GenServer.call/3
#cell:ljknscxzevb4x3mpuppagmq7oloh73s2:2: (file)
POC
Example
Mix.install([
{:kino, "~> 0.11.0"}
])
Section
defmodule Test do
use Kino.JS
use Kino.JS.Live
def new do
Kino.JS.Live.new(__MODULE__, nil)
end
def test(kino) do
Kino.JS.Live.call(kino, :test)
end
def init(nil, ctx) do
{:ok, ctx}
end
def handle_connect(ctx) do
{:ok, %{}, ctx}
end
def handle_call(:test, from, ctx) do
broadcast_event(ctx, "ping", nil)
{:noreply, assign(ctx, caller: from)}
end
def handle_event("pong", _data, ctx) do
Kino.JS.Live.reply(ctx.assigns.caller, "TEST")
{:noreply, ctx}
end
asset "main.js" do
"""
export function init(ctx, data) {
ctx.handleEvent("ping", () => {
ctx.pushEvent("pong", null);
});
}
"""
end
end
{:module, Test, <<70, 79, 82, 49, 0, 0, 15, ...>>, :ok}
This is not working
Test.new()
|> Test.test()
This is working
test = Test.new()
Test.test(test)
"TEST"
@jannikbecher this is expected, note that in order for the client-side code to receive the event, the kino needs to actually be rendered on the page and initialised, which is not the case in the first example :)
@jonatanklosko Ah I see. Is there a way to check whether the kino is rendered? :)
You can keep track of new clients in handle_connect
, just keep in mind that if the notebook is opened in multiple tabs (or the same kino is returned from multiple cells), there will be multiple "renderings" :)