Async HTTP now common, it should be easy in clojure!
Lamina is probably my favorite clojure lib, but it's hard to use directly
The existing interfaces bridging Noir and Lamina are tricky
Let's make something simple!
; Plain Noir
(defpage " /route" []
" I am plain" )
; Noir-async
(defpage-async " /async-route" [] conn
(async-push " I am slightly fancier" ))
Explicit connection object (great for passing between threads)
Explicit push through the connection
sync and async can live side-by-side
Let's get a little fancier
; A delayed response
(defpage-async " /route" [] conn
(set-timeout 3000 #(async-push " Why hello!" )))
set-timeout is provided by noir-async.utils
Since set-timeout uses a timer, this is returned from a separate thread
; An HTTP chunked response
(defpage-async " /always-chunky" [] conn
(async-push conn {:status 200 :chunked true })
(async-push conn " chunk one" )
(async-push conn " chunk two" )
(close-connection conn))
We send the initial header using the map syntax, marking :chunked true
We must explicitly close the connection
(defpage-async " /echo" [] conn
(on-receive conn (fn [m] (async-push conn m))))
on-receive sets up a callback
messages are plain strings
A Final, Super-Fancy Example
(require ['noir-async :as 'na])
(use 'lamina.core)
(na/defpage-async " /river" {} conn
(when (not (na/websocket? conn)) ; Send chunked header to non-websockets
(na/async-push conn {:status 200 :chunked true }))
; ; Send some inital messages after connect
(na/async-push
conn
(json-chunk {" entity" " system" " name" " current-nodes" " body" (nmgr/json-nodes )}))
(na/async-push
conn
(json-chunk {" entity" " system" " name" " current-job" " body" @jmgr/current-job}))
; ; Redirect a lamina stream straight into the socket via lamina.core/siphon
(let [output (na/writable-channel conn)]
(siphon (map* json-chunk ctrl/emitter) output)
(siphon (map* json-chunk jmgr/emitter) output)))
Started as an extraction from actual projects
Attempted to reduce API to as few methods as possible
Used explicit conn
object rather than a binding for threadsafety
Lamina is overkill for most people
Callbacks are simpler than channels
Nothing removed (channels can be pulled out of conn
)