component

alex.ter.weele 2016-11-23T18:43:47.000262Z

I have a database connection object which I’m using as a component, which I can then pass as an argument to database functions, e.g. (db/create conn-component my-thing). This works well.
The problem I’m running into is that whenever the connection is interrupted (database unreachable, network problem, etc.), using a database function will result in an exception. In this situation, the old database connection object becomes useless and I need a new one. How can I use component to solve or avoid this problem?

2016-11-23T19:03:26.000263Z

don't use a database connection as a component

2016-11-23T19:03:43.000264Z

use a connection pool or something you can get a connection from

donaldball 2016-11-23T19:10:42.000265Z

What you can do is implement a defrecord that participates in the pseudo-protocol that clojure.java.jdbc expects from its db-conn argument

donaldball 2016-11-23T19:10:48.000266Z

E.g.:

donaldball 2016-11-23T19:10:57.000267Z

(defrecord DatabasePool [db datasource]
  component/Lifecycle
  (start [this]
    (log/info :msg "Starting database pool")
    (let [{:keys [dbtype host port dbname user password]} db]
      (when-not (= "postgresql" dbtype)
        (throw (ex-info "Unsupported dbtype" {:db db
                                              :dbtype dbtype})))
      (let [options (assoc default-database-pool-options
                           :server-name host
                           :port-number port
                           :database-name dbname
                           :username user
                           :password password)]
        (try
          (let [datasource (with-retries* #(hikari/make-datasource options))]
            (assoc this :datasource datasource))
          (catch Exception e
            (log/error :msg "Error creating database pool"
                       :exception e)
            (throw (ex-info "Invalid database pool" {:db db} e)))))))
  (stop [this]
    (log/info :msg "Stopping database pool")
    (when datasource
      (hikari/close-datasource datasource))
    (assoc this :datasource nil)))

2016-11-23T19:17:18.000268Z

the thing to do, independent of component, is use a connection pool