Reputation: 965
which could be the best way for handle async channels in ring, basically I need get the response of my channel inside my handler and then serve the response
(GET "/slow/:a" [a] (slow-request2 a))
;;this function do a slow operation simulating a slow request
(defn slow-response [a]
(let [ch (!/chan 1)]
(!/go (Thread/sleep 10000)
(print "running slow")
(!/>! ch (+ 1 a)))
ch))
;;based in the recommendation from http://www.reddit.com/r/Clojure/comments/2ka3na/how_do_you_organize_your_coreasync_code/cljbz2q
(defn slow-request [a]
(!/go-loop
[v (!/<! (slow-response a))]
(when v (do
(print "response v")
{:status 200 :body v}))))
(defn slow-request2 [a]
(!/go
(while true
{:status 200 :body (!/<! (slow-response a))})))
unfortunatelly I get this error
java.lang.IllegalArgumentException at /slow/10
No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: clojure.core.async.impl.channels.ManyToManyChannel
seems than the handler is trying response the whole go block instead of my request body, I can't found a solution for handle the response without side-effect except use a blocking response
which could be the best approach in this case?
note: I'm using vertx/ring adapter so http/kit is not an option right now, I need found a way for handle channels in a ring response
Upvotes: 2
Views: 804
Reputation: 71
You need to do a blocking take on the core.async channel in order to force it to a value. Otherwise the handler will return the channel itself and not the value on the channel.
If you need support for async in your requests consider using Pedestal
Also, prefer timeout chan's to Thread/sleep when inside go blocks.
Upvotes: 1