Как связать динамическую переменную?

Как связать динамическую переменную в compojure? Пожалуйста, смотрите мой пример ниже, здесь request-id - это уникальный uuid, который генерируется для каждого запроса API. Я хотел бы иметь возможность доступа к этому идентификатору запроса в последующих методах для ведения журнала и т. Д. Я пытался использовать функцию привязки, но по-прежнему не могу получить доступ к идентификатору запроса в some-page/some-method,

handler.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))))))

некоторые-page.clj

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

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

3 ответа

Решение

Призыв к привязке здесь находится не в том месте. Привязка должна действовать при обработке запроса, а не при создании app/api.

Вы хотите иметь промежуточное программное обеспечение для этого:

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

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

Смотрите также Кольцевые Понятия

В вашем 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*}))

Динамическое связывание - это прекрасный подход, и со временем оно может неуклонно расти по мере роста базы кода, по крайней мере, по сравнению с хранением данных о запросе в самом запросе.

Кольцевая модель поощряет хранение данных о запросе непосредственно в запросе в виде данных, а не в метаданных или средах, таких как связанные переменные.

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

тогда вам не нужно беспокоиться о том, где хранятся привязки потоков, или о других подобных проблемах.

Другие вопросы по тегам