it looks possible by using a custom configure, with a configurator that overrides modify-handshake maybe ? Or using a servlet filter ?
(def configurator
(proxy [ServerEndpointConfig$Configurator] []
(modify-handshake [^ServerEndpointConfig sec ^HandshakeRequest req ^jakarta.websocket.HandshakeResponse rep]
(println (.getHeaders req))))
...
:configure (fn [^ServerEndpointConfig$Builder sec-builder]
(.configurator sec-builder ^ServerEndpointConfig$Configurator configurator))
...
i tried the following without succes đ I may be missing somthingThank you, have looked at configure didnât found headers, found subprotocols (saw someone used them in the browser, where no headers on ws) but still would be nice to have a simpler way
how do subprotocols help ?
you do have access to the query string in an easy way if you want
You define custom sub protocol where token is part of the definition, then read it and authenticate connection But yeah, it would be much more convenient to just get headers in upgrade
also another Q: in the docs related to http://pedestal.io/pedestal/0.6/guides/sse.html a saw core async blocking puts inside demo and also inside heartbeat in the lib. As far as I know pedestal doesnât use virtual threads, so itâs kind of bad? Or am I missing something? Edit. Most importantly I was missing docs, which helpfully saying that you shouldnât spin up a long process inside stream-ready callback
what should be avoided with core async is blocking operations inside a go block, this kind of patterns: (go (let [res (long-http-call)] (>! channel res)))
it looks like you're right, it is doing a blocking operation in the go block in the lib, I couldn't find the one in in the doc though
start-dispatch-loop has a go block that calls send-event, which is blocking
oh wait it's using put!, (and not >!! as I previously thought) so maybe it's ok ?
I meant that sample is using >!! inside SSE fn (stream-ready), also most probably weâre inside some thread pool inside jetty. Could >!! saturate jetty thread pool? But maybe Iâm completely wrong tho
no it's not jetty's thread pools. From what I'm reading start-event-stream calls your stream-ready fn in an async/thread block, so it's ok to do blocking operations here. It starts a regular thread from IIRC an unbounded thread pool.
the problem with go block is that the thread pool is really small so it's easy to exhaust it if many go block are running (and not waiting on <! or >! operations) at the same time.
Oh, I see, but isnât it still bad? Like if you stream to 100k clients
it would be like running 100k future
so probably too much with default settings
I guess it would be better with virtual threads when they will be integrated to core async
probably because virtual thread should not consume resources when you're doing the Thread/sleep call that's in the doc
I have no experience with virtual threads
Thank you @rolthiolliere ! I think I now kinda understand whatâs happening here and why blocking operations are ok Also related to go blocks, if itâs mainly (non blocking) IO probably 8 threads should be enough? If you outsource compute to some other thread, etc?
I'm not sure how to answer that, there's several things...
⢠go blocks have some overhead, binding variable, calling functions etc is a bit slower because of the macro is transforming the code a bit to capture variables and stuff. So (go (fn-that-hides-stuff) ...) is better that (go (complex inlined code) ...)
⢠only 8 go block can run at the same time (but many many more can wait on an operation with <! , 1 million ?? 10 million ?? I never stress tested it). 8 is usually more that the number of core on the machine so normally it's plenty.
⢠if you do computationally intensive operation, it's better to use threads yes. You would not run 10 million computationally intensive operations at the same time anyway. You probably want to bound yourself the executor thread pool for that and have a tight control on it
I just imagine a situation where start-event-stream starts a go block and you use <! inside stream-ready with a caution that you shouldnât really block this fn, I assume it could scale better for multiple concurrent connections
I think so yes
I concur that guide is not so great; adding a thread or a properly-written go around the meat of that dotimes loop would still demonstrate the necessary concepts without conflicting with basic core.async guidelines.