Clojure - 将组件传递给在启动或停止期间未执行的函数
Clojure - pass component to functions not executed during start or stop
在 Stuart Sierra 的组件的 README 中,有一个函数 add-user
作为示例给出,但在其他地方没有看到:
(defn add-user [database username favorite-color]
(execute-insert (:connection database)
"INSERT INTO users (username, favorite_color)"
username favorite-color))
我想它可以在网络服务器路由上执行(例如)。我可以毫不费力地想象 username
和 favorite-colour
将成为该路由的参数,因此在调用 add-user
.
时很容易获得
我想有了这个会使 database
组件成为 web-server
(例如)组件。
但是,我在确定 add-user
的 database
组件 instance 参数的确切来源时遇到了一些问题。
我觉得直接访问 system
(即做 (:database my-system-ns/system))
)来检索它首先会破坏使用组件的部分目的。
例如,如果我使用的是基座,我可能会让我的基座组件(有权访问数据库组件)设置此密钥:
::bootstrap/routes #(deref #'my-routes-ns/routes)
这会是这样的:
;; in my-routes-ns
(defroutes routes [[[ "/add-user" {:post add-user-handler} ]]])
;; same function again for clarity
(defn add-user [database username favorite-color]
(execute-insert (:connection database)
"INSERT INTO users (username, favorite_color)"
username favorite-color))
;; my route handler
(defn add-user-handler [request]
;; How do I get access to the database component from here ?
(add-user database "user" "red"))
如何访问本示例中的 database
组件?
在典型的应用程序中,您可能有一个 web-server
组件依赖于(参见 component/using
)您的 database
组件,以及一组 public 关联的函数使用 database
组件,其消费者可以调用该组件来查询数据库。
web-server
组件将负责设置您的请求处理程序并启动侦听器(如 Jetty)。这将涉及获取 database
组件并将其注入到您的处理程序中,可能是通过部分应用(如果您的处理程序看起来像 (defn handler [database request] …)
,比如说),以便它可以调用 add-user
database
个组件。
请注意,根据您应用的设计,您的设置可能与上述不完全匹配——例如,web-server
只能通过一层或多层中间组件使用 database
组件.
仅供参考,the README of component 建议对一个或多个组件创建闭包,
(defn app-routes
"Returns the web handler function as a closure over the
application component."
[app-component]
;; Instead of static 'defroutes':
(web-framework/routes
(GET "/" request (home-page app-component request))
(POST "/foo" request (foo-page app-component request))
(not-found "Not Found")))
(defrecord WebServer [http-server app-component]
component/Lifecycle
(start [this]
(assoc this :http-server
(web-framework/start-http-server
(app-routes app-component))))
(stop [this]
(stop-http-server http-server)
this))
(defn web-server
"Returns a new instance of the web server component which
creates its handler dynamically."
[]
(component/using (map->WebServer {})
[:app-component]))
在 Stuart Sierra 的组件的 README 中,有一个函数 add-user
作为示例给出,但在其他地方没有看到:
(defn add-user [database username favorite-color]
(execute-insert (:connection database)
"INSERT INTO users (username, favorite_color)"
username favorite-color))
我想它可以在网络服务器路由上执行(例如)。我可以毫不费力地想象 username
和 favorite-colour
将成为该路由的参数,因此在调用 add-user
.
我想有了这个会使 database
组件成为 web-server
(例如)组件。
但是,我在确定 add-user
的 database
组件 instance 参数的确切来源时遇到了一些问题。
我觉得直接访问 system
(即做 (:database my-system-ns/system))
)来检索它首先会破坏使用组件的部分目的。
例如,如果我使用的是基座,我可能会让我的基座组件(有权访问数据库组件)设置此密钥:
::bootstrap/routes #(deref #'my-routes-ns/routes)
这会是这样的:
;; in my-routes-ns
(defroutes routes [[[ "/add-user" {:post add-user-handler} ]]])
;; same function again for clarity
(defn add-user [database username favorite-color]
(execute-insert (:connection database)
"INSERT INTO users (username, favorite_color)"
username favorite-color))
;; my route handler
(defn add-user-handler [request]
;; How do I get access to the database component from here ?
(add-user database "user" "red"))
如何访问本示例中的 database
组件?
在典型的应用程序中,您可能有一个 web-server
组件依赖于(参见 component/using
)您的 database
组件,以及一组 public 关联的函数使用 database
组件,其消费者可以调用该组件来查询数据库。
web-server
组件将负责设置您的请求处理程序并启动侦听器(如 Jetty)。这将涉及获取 database
组件并将其注入到您的处理程序中,可能是通过部分应用(如果您的处理程序看起来像 (defn handler [database request] …)
,比如说),以便它可以调用 add-user
database
个组件。
请注意,根据您应用的设计,您的设置可能与上述不完全匹配——例如,web-server
只能通过一层或多层中间组件使用 database
组件.
仅供参考,the README of component 建议对一个或多个组件创建闭包,
(defn app-routes
"Returns the web handler function as a closure over the
application component."
[app-component]
;; Instead of static 'defroutes':
(web-framework/routes
(GET "/" request (home-page app-component request))
(POST "/foo" request (foo-page app-component request))
(not-found "Not Found")))
(defrecord WebServer [http-server app-component]
component/Lifecycle
(start [this]
(assoc this :http-server
(web-framework/start-http-server
(app-routes app-component))))
(stop [this]
(stop-http-server http-server)
this))
(defn web-server
"Returns a new instance of the web server component which
creates its handler dynamically."
[]
(component/using (map->WebServer {})
[:app-component]))