I'm learning Clojure (1.10) and am writing a small web app using the Luminus framework (3.93), using the Monger client (3.1.0) to connect to a MongoDB instance. Luminus generates some scaffolding code that is to create the database connection pool (using the function monger.core/connect-via-uri
) on startup in <myproject>.db.core
:
(ns myproject.db.core
(:require [monger.core :as mg] ... ))
(defstate db*
:start (-> env :database-url mg/connect-via-uri)
:stop (-> db* :conn mg/disconnect))
...
My problem: if the MongoDB instance is not available at this point, nothing is shown to warn of the problem. Web pages are served, until one requires a call to a Monger function. At this point the app "churns" and then timeouts (set at 30s) with an exception/stacktrace error screen (which, besides being a horrible user experience, may also expose code/data that is supposed to remain secret).
How can I best guard against starting up the application when the prerequisite database is not available?
One (admittedly clumsy) initial attempt is to insert a Monger call into the above startup code. This causes a timeout exception during startup (with an exception message), instead of starting up the web app. What is a better way?
Also, do you know of a way to let a problem like this halt the startup process instead of retrying and churning out failure messages?
(defstate db*
:start (-> env :database-url mg/connect-via-uri
; clumsy way to catch timeouts due to no database when starting up:
(#(mg/get-db-names (:conn %)) %))
:stop (-> db* :conn mg/disconnect))
I'm not an expert on Monger, but this guide on their website shows ways of changing the timeout.
So, maybe change the timeout to 3 seconds or something, then see of you can connect. Otherwise, throw and exception or something.