From 0064e01c19bdc989622027ec1c4ab2e8c9cb513d Mon Sep 17 00:00:00 2001
From: dpsutton <dan@dpsutton.com>
Date: Wed, 11 May 2022 10:47:26 -0500
Subject: [PATCH] Verify active database for `GET api/health` (#22606)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Verify active database for `GET api/health`

Previously unconditionally responded with 200, status "ok" if we were
done initializing, even when we had 1500 stale db connections
somehow (:scream:).

Now attempt to connect to the database:

```shell
❯ http get localhost:3000/api/health -pb
{
    "status": "ok"
}

❯ http get localhost:3000/api/health
HTTP/1.1 503 Service Unavailable
...
{
    "status": "Error getting db connection"
}
```

and logging to the server
```
2022-05-10 22:05:16,911 WARN server.routes :: Error in api/health database check
java.lang.ArithmeticException: Divide by zero
	at clojure.lang.Numbers.divide(Numbers.java:190)
	at clojure.lang.Numbers.divide(Numbers.java:3911)
	at metabase.server.routes$fn__122320.invokeStatic(routes.clj:51)
```

* Reuse `sql-jdbc.conn/can-connect-with-spec?` for api/health
---
 src/metabase/server/routes.clj | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/metabase/server/routes.clj b/src/metabase/server/routes.clj
index 6f57f892ee3..8e8dce24446 100644
--- a/src/metabase/server/routes.clj
+++ b/src/metabase/server/routes.clj
@@ -1,15 +1,19 @@
 (ns metabase.server.routes
   "Main Compojure routes tables. See https://github.com/weavejester/compojure/wiki/Routes-In-Detail for details about
    how these work. `/api/` routes are in `metabase.api.routes`."
-  (:require [compojure.core :refer [context defroutes GET]]
+  (:require [clojure.tools.logging :as log]
+            [compojure.core :refer [context defroutes GET]]
             [compojure.route :as route]
             [metabase.api.dataset :as api.dataset]
             [metabase.api.routes :as api]
             [metabase.core.initialization-status :as init-status]
+            [metabase.db.connection :as mdb.connection]
+            [metabase.driver.sql-jdbc.connection :as sql-jdbc.conn]
             [metabase.plugins.classloader :as classloader]
             [metabase.public-settings :as public-settings]
             [metabase.server.routes.index :as index]
             [metabase.util :as u]
+            [metabase.util.i18n :refer [trs]]
             [ring.util.response :as response]))
 
 (u/ignore-exceptions (classloader/require '[metabase-enterprise.sso.api.routes :as ee.sso.routes]))
@@ -43,9 +47,15 @@
   (GET "/" [] index/index)
   (GET "/favicon.ico" [] (response/resource-response (public-settings/application-favicon-url)))
   ;; ^/api/health -> Health Check Endpoint
-  (GET "/api/health" [] (if (init-status/complete?)
-                          {:status 200, :body {:status "ok"}}
-                          {:status 503, :body {:status "initializing", :progress (init-status/progress)}}))
+  (GET "/api/health" []
+       (if (init-status/complete?)
+         (try (if (sql-jdbc.conn/can-connect-with-spec? {:datasource (mdb.connection/data-source)})
+                {:status 200, :body {:status "ok"}}
+                {:status 503 :body {:status "Unable to get app-db connection"}})
+              (catch Exception e
+                (log/warn e (trs "Error in api/health database check"))
+                {:status 503 :body {:status "Error getting app-db connection"}}))
+         {:status 503, :body {:status "initializing", :progress (init-status/progress)}}))
   ;; ^/api/ -> All other API routes
   (context "/api" [] (fn [& args]
                        ;; Redirect naughty users who try to visit a page other than setup if setup is not yet complete
-- 
GitLab