0

我正在尝试在 ring/compojure 应用程序中设置 LevelDB,并寻找一种惯用的方式来将打开的数据库描述符访问到每个请求中。

例如:

(defn -main
  "I don't do a whole lot ... yet."
  [& args]

  (println "Opening LevelDB file in db/main")
  (with-open [main-db (db/open "db/main")]

    (println "Running server on port 3000")
    (run-jetty #'web/app {:port 3000})))

您如何将main-db描述符访问到请求处理程序中?

IE。:

(defroutes handler

  (GET "/test" []
    (db/put main-db (.getBytes "testKey2") (.getBytes "testValue2"))
    "<h1>Hello World</h1>")

PS:我正在使用 Sedward 的 leveldb-clj 库并将其打包成 clojar:https ://clojars.org/org.clojars.aircart/leveldb-clj

4

1 回答 1

0

如果你想在你的应用程序中使用一个全局描述符,最简单的选择可能是在顶级 Var 中存储一个承诺或延迟:

(def level-db-descriptor (promise))

(defn open [...]
  ...
  (deliver level-db-descriptor ...))

(open ...)

;; or

(def level-db-descriptor (delay (open ...)))

然后说你什么@level-db-descriptor时候需要去做。

如果您需要偶尔更换描述符,这不是很好;但是,您也可以在保留使用@level-db-descriptor模式的同时支持这一点:

(defprotocol PDescriptorBox
  (put-descriptor! [this d])
  (get-descriptor [this]))

(defn make-descriptor-box []
  (let [box (clojure.lang.Box. nil)]
    (reify
      clojure.lang.IDeref
      (deref [this] (get-descriptor this))
      PDescriptorBox
      (get-descriptor [this]
        (locking this
          (.-val box)))
      (put-descriptor! [this d]
        (locking this
          (set! (.-val box) d))))))

当然,您可以put-descriptor!用更复杂的东西替换(也许只有在对旧描述符做了一些事情后才产生新的描述符)。

如果您希望能够并行运行应用程序的多个实例,那么这些单独的实例可能会使用某种状态容器,并且您可能希望使用它们来存储描述符而不是顶级 Var。

于 2013-07-19T09:33:04.800 回答