代码之家  ›  专栏  ›  技术社区  ›  Freid001

如何绑定动态变量?

  •  2
  • Freid001  · 技术社区  · 7 年前

    如何在compojure中绑定动态变量?请参见下面的示例,这里的请求id是为每个api请求生成的唯一uuid。我希望能够在后续的日志记录等方法中访问此请求id。我已尝试使用绑定功能,但仍然无法访问 请求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*}))
    
    3 回复  |  直到 7 年前
        1
  •  5
  •   Joost Diepenmaat    7 年前

    在此处调用binding是在错误的位置。绑定应该在处理请求时生效,而不是在构建应用程序/api时生效。

    您需要一些中间件来完成此操作:

    (defn with-request-id 
      [f]
      (fn [request]
        (binding [*request-id* (generate-request-id)]
          (f request)))
    
    (def app
      (with-request-id
        (api ... ))
    

    另请参见 Ring Concepts

        2
  •  1
  •   clartaq    7 年前

    在您的 some_app.some_page 命名空间,您需要 require 命名空间,其中 *request-id* 已声明。类似于:

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

    然后您可以参考 *请求id* 例如:

    (def some-method []
      (log/info {:request-id hndlr/*request-id*}))
    
        3
  •  1
  •   Arthur Ulfeldt    7 年前

    动态绑定是一种很好的方法,随着时间的推移,它可能会随着代码库的增长而不适地增长,至少与在请求本身中存储有关请求的数据相比。

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

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

    然后,您就不需要担心线程绑定保存在哪里或其他类似的问题。