Created
June 13, 2019 17:07
-
-
Save camsaul/81bc81338726d4e618b8a36ce7433ff9 to your computer and use it in GitHub Desktop.
Mongo driver ideas
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn- normalize-details [details] | |
(let [{:keys [dbname host port user pass ssl authdb tunnel-host tunnel-user tunnel-pass additional-options] | |
:or {port 27017, pass "", ssl false}} details | |
;; ignore empty :user and :pass strings | |
user (when (seq user) | |
user) | |
pass (when (seq pass) | |
pass) | |
authdb (if (seq authdb) | |
authdb | |
dbname)] | |
{:host host | |
:port port | |
:user user | |
:authdb authdb | |
:pass pass | |
:dbname dbname | |
:ssl ssl | |
:additional-options additional-options})) | |
(defn- srv-connection-info | |
"Docstring goes here" | |
[{:keys [host port user authdb pass dbname ssl additional-options]}] | |
(let [conn-opts (connection-options-builder :ssl? ssl, :additional-options additional-options) | |
authdb (if (seq authdb) | |
authdb | |
dbname) | |
conn-str (format "mongodb+srv://%s:%s@%s/%s" user pass host authdb)] | |
{:type :srv | |
:uri (MongoClientURI. conn-str conn-opts)})) | |
(defn- normal-connection-info | |
"Docstring goes here" | |
[{:keys [host port user authdb pass dbname ssl additional-options]}] | |
(let [server-address (mg/server-address host port) | |
credentials (when user | |
(mcred/create user authdb pass)) | |
^MongoClientOptions$Builder opts (connection-options-builder :ssl? ssl, :additional-options additional-options)] | |
{:type :normal | |
:server-address server-address | |
:options (-> opts .build)})) | |
(defn- fqdn? | |
"A very simple way to check if a hostname is fully-qualified: | |
Check if there are exactly two periods in the name." | |
[host] | |
(= 2 (-> host frequencies (get \.)))) | |
(defn- details->mongo-connection-info [{:keys [host], :as details}] | |
((if (fqdn? host) | |
srv-connection-info | |
normal-connection-info) details)) | |
(defmulti ^:private connect | |
"Connect to MongoDB using Mongo `connection-info`, return a tuple of `[mongo-client db]`, instances of `MongoClient` | |
and `DB` respectively." | |
{:arglists '([connection-info])} | |
:type) | |
(defmethod connect :srv | |
[{:keys [^MongoClientURI uri]}] | |
(let [mongo-client (MongoClient. uri)] | |
(if-let [db-name (.getDatabase uri)] | |
[mongo-client (.getDB conn db-name)] | |
(throw | |
(IllegalArgumentException. | |
(str (trs "No database name specified in URI. Monger requires a database to be explicitly configured."))))))) | |
(defmethod connect :normal | |
[:keys [server-address options]] | |
(let [do-connect (partial mg/connect server-address options) | |
mongo-client (if credentials | |
(do-connect credentials) | |
(do-connect))] | |
[mongo-client (mg/get-db mongo-client dbname)])) | |
(defn -with-mongo-connection | |
"Run `f` with a new connection (bound to `*mongo-connection*`) to `database`. Don't use this directly; use | |
`with-mongo-connection`." | |
[f database] | |
(let [details (database->details database)] | |
(ssh/with-ssh-tunnel [details-with-tunnel details] | |
(let [connection-info (details->mongo-connection-info (normalize-details details-with-tunnel)) | |
[mongo-client db] (connect connection-info)] | |
(log/debug (u/format-color 'cyan (trs "Opened new MongoDB connection."))) | |
(try | |
(binding [*mongo-connection* db] | |
(f *mongo-connection*)) | |
(finally | |
(mg/disconnect mongo-client) | |
(log/debug (u/format-color 'cyan (trs "Closed MongoDB connection."))))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment