Open wiseac opened 1 year ago
@wiseac I've never seen this one. Can you provide a small example of how to replicate this? Thanks
Closing due to feedback. Please reopen if you can provide more info.
I'm also encountering the same error but in a rather unpredictable fashion (hence difficult to reproduce). Comparing the Genie log with the console message in the browser I noticed the following:
and then in the Console at around the same timestamp
However, the same error appears later in the Console
but this time there is no concomitant error in Genie.
Moreover, there are other errors in the Console such as
which sometimes do not give rise to any error in Genie, but at other times do as in this example:
I don't know if concurrency is related to the issue, but in my use case I am continually reading a stream of MQTT messages and updating reactive plots every second. The code to retrieve the latest MQTT messages from a database and update the reactive variables is running in its own task.
Regarding the "Could not decode a text frame as UTF-8" there is a discussion of some possible solutions here https://stackoverflow.com/questions/17126227/could-not-decode-a-text-frame-as-utf-8 but I'm not sure if this is a Websockets.jl issue or a Genie issue.
Looks like the socket connection is closed when Genie attempts to push some data. Hence the error message which could be read as sending requires that the websocket is not closed
(while in fact it is closed).
Btw, that error is not thrown by Genie, but comes from WebSockets/HTTP package.
I encountered a very similar issue when sending messages to the websocket asynchronously.
In normal circumstances this doesn't happen. But if you have external async events triggering updates then this can occur.
The root cause is that Socket.send(ws, message)
doesn't protect the ws from being written to by other processes. When this happens, the two messages get mixed and the messages are misunderstood.
@essenciary
We could solve this by a setup like the following:
using Genie.WebChannels.HTTP.WebSockets
using Sockets
const WS_QUEUES = Dict{UInt, Channel{Tuple{String, Channel{Nothing}}}}()
function message_safe(clientid, message::String)
ws = Genie.WebChannels.CLIENTS[clientid].client
future = Channel{Nothing}(1)
q = get!(WS_QUEUES, clientid) do
println("Setting up websocket queue for $(repr(clientid)) ...")
queue = Channel{Tuple{String, Channel{Nothing}}}(10)
t = @async while true
mymessage, myfuture = take!(queue)
try
Sockets.send(ws, mymessage)
finally
println("future: $myfuture")
println(mymessage)
put!(myfuture, nothing)
end
end
queue
end
put!(q, (message, future))
take!(future) # Wait until the message is processed
end
If you want to test the approach, simply start any Genie App, open the dev tools to observe the browser's console and execute the following
say_secure(clientid, x) = message_safe(clientid,
Genie.WebChannels.tagbase64encode(""">eval:console.log($(js_attr(x)))""")
)
say(ws::WebSocket, x) = send(ws,
Genie.WebChannels.tagbase64encode(""">eval:console.log($(js_attr(x)))""")
)
say(clientid::UInt, x::String) = say(Genie.WebChannels.CLIENTS[clientid].client, x)
ws = Genie.WebChannels.clients()[1].client
client = Genie.WebChannels.id(ws)
say(client, "hello")
# will say 'hello' at the browser console
say_secure(client, "hello2")
# will say 'hello2' at the browser console
# this will work
for i in 1:20
@async say_secure(client, "hello $i you")
end
# this will produce the UTF-8 error as described in the issue above
for i in 1:20
@async say(client, "hello $i")
end
Here I set up the handler during the first send()
but we could make it part of the subscription.
@hhaensel thanks! It would make sense to have this as the default - would you like to make a PR please?
In these dev logs, i keep getting this error.
Error: 2023-07-26 16:14:02 ArgumentError("send() requires
!(ws.writeclosed)") └ @ Genie.WebChannels /home/crd/.julia/packages/Genie/XpFvB/src/WebChannels.jl:239
It happens pretty often and I'm not sure why?
┌ Error: 2023-07-26 16:14:02 ArgumentError("send() requires
!(ws.writeclosed)") └ @ Genie.WebChannels /home/crd/.julia/packages/Genie/XpFvB/src/WebChannels.jl:239 ┌ Error: 2023-07-26 16:14:53 ArgumentError("send() requires
!(ws.writeclosed)") └ @ Genie.WebChannels /home/crd/.julia/packages/Genie/XpFvB/src/WebChannels.jl:239 ┌ Error: 2023-07-26 16:15:02 ArgumentError("send() requires
!(ws.writeclosed)") └ @ Genie.WebChannels /home/crd/.julia/packages/Genie/XpFvB/src/WebChannels.jl:239
I am running a global model webpage and have a for loop running for long periods at a time 1 hr+.
Best, W