“Unsupported Context on :enter” 当 reitit 拦截器更新为异步时

huangapple go评论46阅读模式
英文:

"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 协议 的一个方法,并且对于任何对象都会返回 falsesieppari/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.

huangapple
  • 本文由 发表于 2023年5月30日 01:39:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76359332.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定