2

如何在 compojure 中绑定动态变量?请参阅下面的示例,这里的 request-id 是为每个 api 请求生成的唯一 uuid。我希望能够在后续的日志记录方法中访问此 request- id。我尝试使用绑定功能,但仍然无法在some-page/some-method.

处理程序.clj

(ns some_app.handler
  (:require
    [compojure.api.sweet :refer :all]
    [compojure.route :as route]
    [some_api.some_page :as some-page]))

(def ^:dynamic *request-id*
  nil)

(defn ^:private generate-request-id []
  (str (java.util.UUID/randomUUID)))

(def app
  (binding [*request-id* (generate-request-id)]
    (api
      (context "/api" [] (GET "/some-page" [] (some-page/some-method))))))

一些页面.clj

(ns some_app.some_page
(:require
        [clojure.tools.logging :as log]))

(def some-method []
  (log/info {:request-id *request-id*}))
4

3 回答 3

5

这里对绑定的调用是在错误的地方。绑定应该在处理请求时生效,而不是在构建 app/api 时生效。

你想要一些中间件来做到这一点:

(defn with-request-id 
  [f]
  (fn [request]
    (binding [*request-id* (generate-request-id)]
      (f request)))

(def app
  (with-request-id
    (api ... ))

另请参阅环概念

于 2018-01-02T16:35:58.427 回答
1

在您的some_app.some_page命名空间中,您需要声明require的命名空间*request-id*。就像是:

(ns some_app.some_page
  (:require
    [clojure.tools.logging :as log]
    [some_app.handler :as hndlr))

然后你可以参考*request-id*类似的:

(def some-method []
  (log/info {:request-id hndlr/*request-id*}))
于 2018-01-02T18:47:48.457 回答
1

动态绑定是一种很好的方法,随着时间的推移,它可能会随着代码库的增长而变得异常庞大,至少与将有关请求的数据存储在自身的请求中相比是如此。

环模型鼓励将有关请求的内容作为数据直接存储在请求中,而不是存储在元数据或绑定变量之类的环境中。

(defn with-request-id 
  [f]
  (fn [request]
      (f (assoc request :request-id (generate-request-id)))

那么您无需担心线程绑定的保留位置或其他此类问题。

于 2018-01-02T20:23:00.497 回答