How do I check Monger connection in a Luminus app (MongoDB not available)?

116 Views Asked by At

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))
2

There are 2 best solutions below

0
On

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.

1
On

you can try to ping the db to check its availability:

(mg/command db {:ping 1})

Moreover, you can create a scheduler (for example here this) to check the db's status periodically