懒洋洋地定义代理

时间:2015-09-22 15:32:23

标签: clojure

我正在创建一个代理,用于将更改写回数据库(如Clojure Programming中基于代理的后写日志中所述)。

这工作正常,但我很难创建代理。我不想将其创建为def,因为我不希望在我的测试运行时创建它(我看到当测试加载表单时池启动,即使我使用with-redefs来设置测试值。)

我开始使用的代码是(使用c3p0池):

(def dba (agent (pool/make-datasource-spec (u/load-config "db.edn"))))

我尝试将代理设为nil,并调查了如何在我的应用程序的主要部分设置它,当它真正需要时。但是,与原子相比,它似乎不是一个等价的reset!函数。并且以下代码也未能说代理没有错误,因此不需要重新启动:

(when (not @dba)
  (restart-agent dba (create-db-pool)))

所以目前,我有一个包含代理的原子,然后我会这样做:

(def dba (atom nil))
;; ...
(defn init-db! []
  (when (not @dba)
    (log/info "Creating agent for pooled connection")
    (reset! dba (agent (create-db-pool))))

但是我必须@@dba来引用代理的内容(即池),这让我觉得这很疯狂。

是否有更明显的方式来懒惰地创建池代理?

1 个答案:

答案 0 :(得分:3)

delay对于此类案例非常有用。它会在第一次读取时创建项目。因此,如果您的测试没有读取它,则不会创建它。

user=> (def my-agent (delay (do (println "im making the agent now") (agent 0))))
#'user/my-agent
user=> 
user=> @my-agent
im making the agent now
#object[clojure.lang.Agent 0x2cd73ca1 {:status :ready, :val 0}]