使用带有core.async通道的http-kit长轮询

时间:2014-07-03 09:12:07

标签: http asynchronous clojure core.async http-kit

我有一些长时间运行的进程,它会在进程完成时返回一个core.async通道,并在其上显示结果。

现在我想使用HTTP-kit进行长轮询来返回结果。 不幸的是,我有点困惑这样做的正确方法是什么。

目前我有一个处理程序(连接到路由),它启动处理调用并在完成后发送结果:

(defn handler
  [request]
  (let [c (process request)] ;; long running process that returns a channel
    (http/with-channel request channel
      (http/send! channel {:status 200
                           :body (<!! (go (<! c)))))
      (http/on-close channel (fn [_] (async/close! c))))))

它有效,但我不确定这是否正确。

编辑,因为<!!正在阻止我现在在go-loop中尝试非阻塞变体

(defn handler
  [request]
  (let [c (process request)]
    (http/with-channel request channel
      (async/go-loop [v (<! c)]
        (http/send! channel {:status 200
                             :body v}))
      (http/on-close channel (fn [_] (async/close! c))))))

1 个答案:

答案 0 :(得分:1)

为什么不在go块中发送频道?

(http/with-channel request channel
  (go (http/send! channel (<! c))))

<!!正在阻止 - 因此,只需在处理程序中直接调用<!! c,您的代码就没有任何优势:

(defn handler [request] (let [c (process request)] ;; long running process that returns a channel {:status 200 :body (<!! c)}))


编辑以回应问题更新:更新后的代码正常工作 - 这是一个功能齐全的命名空间,对我有用:

(ns async-resp.core
  (:require [org.httpkit.server :as http]
            [clojure.core.async :as async :refer (<! >! go chan go-loop close! timeout)]))

(defn process
  [_]
  (let [ch (chan)]
    (go
      (<! (timeout 5000))
      (>! ch "TEST"))
    ch))

(defn test-handler
  [request]
  (let [c (process request)]
    (http/with-channel request channel
      (go-loop [v (<! c)]
        (http/send! channel {:status 200
                             :body v}))
      (http/on-close channel (fn [_] (close! c))))))

(defn run
  []
  (http/run-server test-handler {}))

截至当前时刻,我不得不手动将tools.analyzer.jvm依赖项添加到project.clj - 因为我按原样使用core.async进行编译失败。

检查您是否正在运行最新的core.async和分析器?