JuliaGizmos / WebIO.jl

A bridge between Julia and the Web.
https://juliagizmos.github.io/WebIO.jl/latest/
Other
228 stars 64 forks source link

Pushing an observable to multiple clients no longer works in WebIO 0.8.9 #337

Open rdeits opened 5 years ago

rdeits commented 5 years ago

With WebIO 0.8.9, opening the same scope through multiple frontends results in only one frontend getting the observable updates. This is breaking the MeshCat.jl tests.

Here is a MWE:

using WebIO, Mux, Blink, JSExpr

scope = Scope()

# updates to this update the UI
count = Observable(scope, "count", 1)

onjs(count, # listen on JavaScript
     JSExpr.@js x->this.dom.querySelector("#count").textContent = x)

scope.dom = dom"div"(
    dom"div#count"(string(count[])),
)

@async while true
    count[] += 1
    sleep(1)
end

WebIO.webio_serve(Mux.page("/", req -> scope), 8000)

w = Window()
body!(w, scope)

If you comment out the body!(w, scope) line and just open localhost:8000 in your browser, then everything is fine (the counter updates once per second). Likewise, if you comment out the webio_serve line, then a Blink window opens up and shows the counter updating. But if you keep both lines in, then the Blink window updates but the localhost:8000 page does not.

This works correctly with WebIO 0.8.8 but fails with 0.8.9.

Tested with Blink 0.12.0, Mux 0.7.0, JSExpr 0.5.0.

rdeits commented 5 years ago

The behavior seems to depend on the order in which you open localhost:8000 vs. when the Blink window connects: whichever frontend connects first seems to get the updates, while the other does not.

twavv commented 5 years ago

Thanks for this. Will fix ASAP.

twavv commented 5 years ago

@rdeits If you could code-review the PR I just put up, I'd be very grateful (@shashi your input would be appreciated too).

I ended up having to rework the way that new connections are handled in order to make the tests pass but I think it's for the better. I'm not sure if this is particularly threadsafe but that's a bridge we'll come to (...maybe). I think it's strictly an improvement on what was there before.

rdeits commented 5 years ago

It looks like this isn't entirely fixed. I can easily produce a similar error by trying to open two Blink windows:

using WebIO, JSExpr, Blink

scope = Scope()
node = dom"div#panel"("")
obs = Observable{String}(scope, "comm", "")
onjs(obs, @js val -> begin
     @var panel = this.dom.querySelector("#panel")
     console.log("val:", val);
     panel.textContent = val
 end)
scope(node)

w1 = Window()
body!(w1, scope)
w2 = Window()
body!(w2, scope)

obs[] = "hello"

The first window shows hello, while the second is blank.

Tested with WebIO master and the following package status:

(webio-test) pkg> st
    Status `~/Downloads/webio-test/Project.toml`
  [ad839575] Blink v0.12.0
  [97c1335a] JSExpr v0.5.1
  [0f1e0344] WebIO v0.8.11 [`dev/WebIO`]
JobJob commented 4 years ago

I think that example does work if you add, e.g., sleep(0.5) between body!(w2, scope) and obs[] = "hello", which maybe warrants a separate issue.

~Possibly something that might be addressed as part of https://github.com/JuliaGizmos/WebIO.jl/issues/258~ Actually, the fact that it works for the first window and not the second, does make it seem like it's related to this. Still, may make sense to track that example in a separate issue.