«Неподдерживаемый контекст при :enter», когда перехватчики reitit обновляются до асинхронных

Я работаю над http-приложением reitit, которое использует перехватчики.

Ниже мой код

      (ns ic.reitit-interceptor-multithreading)

(require '[reitit.ring :as ring])
(require '[reitit.http :as http])
(require '[reitit.interceptor.sieppari :as sieppari])
(require '[clojure.core.async :refer [go]])
(defn interceptor [number]
  {:enter (fn [ctx]
            (go
              (println "in enter interceptor" number (.getName (Thread/currentThread)))
              (update-in ctx [:request :number] (fnil + 0) number)))})

(def app
  (http/ring-handler
   (http/router
    ["/api"
     {:interceptors [(interceptor 1)]}

     ["/number"
        {:interceptors [(interceptor 10)]
         :get {:interceptors [(interceptor 100)]
               :handler (fn [req]
                          (println "in handler")
                          {:status 200
                           :body (select-keys req [:number])})}}]])

   ;; the default handler
   (ring/create-default-handler)

   ;; executor
   {:executor sieppari/executor}))

Когда я выполняю код в repl, я получаю ошибку:

      (require '[ic.reitit-interceptor-multithreading :refer :all])
(app {:request-method :get, :uri "/api/number"})

Я получаю следующую ошибку:

Загрузка src/ic/reitit_interceptor_multithreading.clj... выполнена (приложение {:request-method :get, :uri "/api/number"}) Ошибка выполнения (ExceptionInfo) в sieppari.core/-invalid-context-type! (core.cljc:34). Неподдерживаемый контекст для :enter - clojure.core.async.impl.channels.ManyToManyChannel@4abe39b8 в перехватчике ввода 1 async-dispatch-3

Когда я удаляюgoмакрос из функции ввода перехватчика, тогда он работает нормально.

Как я могу решить эту проблему?

1 ответ

Попробуйте добавить[sieppari.async.core-async :as ca]вnsопределение:

      (ns ic.reitit-interceptor-multithreading
  (:require
    [reitit.ring :as ring]
    [reitit.http :as http]
    [reitit.interceptor.sieppari :as sieppari]
    [clojure.core.async :refer [go]]
    [sieppari.async.core-async :as ca])
  (:gen-class))

Тогда позвони(app {:request-method :get, :uri "/api/number"})снова.

Возможно, есть более простой способ, поэтому вот полное объяснение:

Посмотрите трассировку стека и посмотрите, какие функции вызываются:

Перехватчик должен вернуть контекстную карту (c/context?) или асинхронный канал (a/async?).goдолжен вернуть асинхронный канал, поэтому вы будете искать определение.async?это методAsyncContextпротокол и возврат falseдля любого объекта. sieppari/async/core_async.cljc расширяет этот протокол на асинхронные каналы, которые должны возвращатьtrue.

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