user1050817
user1050817

Reputation: 965

any simple solution for use clojure core async with ring (vertx/ring adapter)

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

Answers (1)

gvickers
gvickers

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

Related Questions