I'm writing an application server in Clojure that will use ClojureScript on the client.
I'd like to find an efficient, idiomatic way to push data from the server to the client as realtime events, ideally using a some combination of:
- http-kit
- core.async
- Ring
(But I'm open to other possibilities)
Can anyone provide a good example / approach to doing this?
I'm developed one project now, where i had the exact same requirement, i used pedestal service in combination with core.async to implement SSE and it's working really well.
Unfortunately, i can't open-source this work now, but basically, i did something like the snippets below, only more complicated because of authentication, which is not particularly easy in SSE from browser, because you can't pass any custom headers in yout 'new EventSource(SOME_URI);' call.
So the snippets:
One "problem" i encountered is the default way how pedestal handles dropped SSE connections.
Because of the scheduled heartbeat job, it logs exception whenever connection is dropped and you didn't call end-event-stream context.
I wish there was a way to disable/tweak this behavior, or at least provide my own tear-down function which will be called whenever heartbeat job fails with EofException.
I prefer to use aleph, here is the wiki, you can simply use
wrap-ring-handler
function to wrap existed handlers.For the 'push' function, most useful part is aleph's async handler. It builds on top of netty, not a one connection one thread model, so the server side do not need worry about the tcp connection count.
Some implement details:
There are more ways here : http://en.wikipedia.org/wiki/Push_technology
I've been trying out the library Chord recently, and I really like it.
It provides a small core.async wrapper around the Websocket support in http-kit.
From the github page:
On the Server
On the Client
I think it's still in early stages though - it doesn't handle disconnections yet.