«Неподдерживаемый контекст при :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
.