Использование длинного опроса http-kit с каналами core.async

У меня есть какой-то долго работающий процесс, который возвращает канал core.async с результатом на нем, когда процесс завершится.

Теперь я хотел бы вернуть этот результат с помощью длинного опроса с HTTP-комплектом. К сожалению, я немного запутался, как правильно поступить.

В настоящее время у меня есть обработчик (подключен к маршруту), который инициирует вызов обработки и отправляет результат по завершении:

(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 ответ

Почему бы не отправить на канал в блоке 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 и анализатора?

Другие вопросы по тегам