英文:
"Unsupported Context on :enter " when reitit interceptors are updated to async
问题
I'm working on reitit http application which uses interceptors.
Below is my code
(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 ])
(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}))
When I'm executing the code in repl I get error -
(require '[ic.reitit-interceptor-multithreading :refer :all])
(app {:request-method :get, :uri "/api/number"})
The error I get is -
Loading src/ic/reitit_interceptor_multithreading.clj... done
(app {:request-method :get, :uri "/api/number"})
Execution error (ExceptionInfo) at sieppari.core/-invalid-context-type! (core.cljc:34).
Unsupported Context on :enter - clojure.core.async.impl.channels.ManyToManyChannel@4abe39b8
in enter interceptor 1 async-dispatch-3
When I remove go
macro from interceptor enter function then it is working fine.
How can I fix this issue?
英文:
I'm working on reitit http application which uses interceptors.
Below is my code
(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 ])
(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}))
When I'm executing the code in repl I get error -
(require '[ic.reitit-interceptor-multithreading :refer :all])
(app {:request-method :get, :uri "/api/number"})
The error I get is -
> Loading src/ic/reitit_interceptor_multithreading.clj... done
> (app {:request-method :get, :uri "/api/number"})
> Execution error (ExceptionInfo) at sieppari.core/-invalid-context-type! (core.cljc:34).
> Unsupported Context on :enter - clojure.core.async.impl.channels.ManyToManyChannel@4abe39b8
> in enter interceptor 1 async-dispatch-3
When I remove go
macro from interceptor enter function then it is working fine.
How can I fix this issue?
答案1
得分: 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 ]
[sieppari.async.core-async :as ca])
(:gen-class))
然后再次调用 (app {:request-method :get, :uri "/api/number"})
。
也许有一种更简单的方法,所以这里是完整的解释:
查看堆栈跟踪并查看调用的哪些函数:
拦截器必须返回上下文映射(c/context?
)或异步通道(a/async?
)。 go
应该返回异步通道,因此您将寻找 async?
的定义。 async?
是 AsyncContext
协议 的一个方法,并且对于任何对象都会返回 false
。 sieppari/async/core_async.cljc 扩展了这个协议以支持异步通道,应该返回 true
。
英文:
Try to add [sieppari.async.core-async :as ca]
into ns
definition:
(ns ic.reitit-interceptor-multithreading
(:require
[reitit.ring :as ring]
[reitit.http :as http]
[reitit.interceptor.sieppari :as sieppari]
[clojure.core.async :refer ]
[sieppari.async.core-async :as ca])
(:gen-class))
Then call (app {:request-method :get, :uri "/api/number"})
again.
Maybe there is an easier way, so here is full explanation:
Look into a stack trace and see, which functions are called:
Interceptor has to return context map (c/context?
) or async channel (a/async?
). go
should return the async channel, so you will look for async?
definition. async?
is a method of AsyncContext
protocol and returns false
for any object. sieppari/async/core_async.cljc extends this protocol to async channels, which should return true
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论