How to manage database connection in Clojure?

Hum… a little, except you don’t have to def conn-options. I’ve used that as a placeholder. The code in the deref would be polling logic to grab the parens from whatever runtime config source you want. For example:

(def conn
  (delay
    (create-connection
      {:jdbc-url (env :database-url)
       ... }))

That’s the assumption with delay, that you can poll for the params at runtime from somewhere which should be available by the time you first need the conn.

You can still split it out, either delaying the conn-options, or what I’d suggest is making it a function.

(defn get-conn-options []
  {:jdbc-url (env :database-url)
   ...}))

(def conn
  (delay
    (create-connection
      (get-conn-options))))

In a prod setting, I’d wrap the call to get-conn-options in a retry as well, within the delay itself, with some policy of how long to retry before just killing the application and raising an alarm.

If you can’t poll, that’s where you can instead use promise. That be nice say if you’re waiting for user input for it. You can just deliver it to the promise whenever its given to your app, and everything else can block waiting until it’s been provided if in a multi-threaded scenario.

(def conn
  (promise))

(defn -main [& args]
  (let [_ (println "What is your DB url?")
        url (read-line)
        _ (println "What is your username?"
        username (read-line)
        _ (println "What is your password?"
        password (read-line)]
    (deliver conn
      (create-connection
        {:url url :user username :pass password}))))

In my opinion, neither are mutating. That might be philosophical, but both delay and promise are single valued objects that can never change after being assigned a value. They just allow to control the exact time at which that value is assigned.

2 Likes