Merge pull request #6 from eva-healthtech/implicit-transaction

Add a helper method for implicit transactions
This commit is contained in:
gnarroway 2021-05-22 09:37:32 +08:00 committed by GitHub
commit 97ea4ea2b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 35 deletions

View file

@ -145,6 +145,20 @@
(execute [_] (body))) (execute [_] (body)))
(->TransactionOptions opts)))) (->TransactionOptions opts))))
(def ^:dynamic *session* nil)
(defn with-implicit-transaction
"Automatically sets the session / transaction for all mongo operations
within the scope, using a dynamic binding"
[{:keys [^MongoClient client transaction-opts session-opts] :or {transaction-opts {} session-opts {}}} body]
(with-open [^ClientSession session (start-session client session-opts)]
(binding [*session* session]
(with-transaction
*session*
body
transaction-opts))))
;;; Utility ;;; Utility
(defn connect-to-db (defn connect-to-db

View file

@ -1,6 +1,7 @@
(ns mongo-driver-3.collection (ns mongo-driver-3.collection
(:refer-clojure :exclude [find empty? drop]) (:refer-clojure :exclude [find empty? drop])
(:require [mongo-driver-3.model :refer :all]) (:require [mongo-driver-3.model :refer :all]
[mongo-driver-3.client :refer [*session*]])
(:import (com.mongodb MongoNamespace) (:import (com.mongodb MongoNamespace)
(com.mongodb.client MongoDatabase MongoCollection ClientSession) (com.mongodb.client MongoDatabase MongoCollection ClientSession)
(com.mongodb.client.model IndexModel) (com.mongodb.client.model IndexModel)
@ -67,6 +68,7 @@
(aggregate db coll pipeline {})) (aggregate db coll pipeline {}))
([^MongoDatabase db coll pipeline opts] ([^MongoDatabase db coll pipeline opts]
(let [{:keys [^ClientSession session allow-disk-use? ^Integer batch-size bypass-document-validation? keywordize? raw?] :or {keywordize? true raw? false}} opts (let [{:keys [^ClientSession session allow-disk-use? ^Integer batch-size bypass-document-validation? keywordize? raw?] :or {keywordize? true raw? false}} opts
^ClientSession session (or session *session*)
it (cond-> (if session it (cond-> (if session
(.aggregate (collection db coll opts) session ^List (map document pipeline)) (.aggregate (collection db coll opts) session ^List (map document pipeline))
(.aggregate (collection db coll opts) ^List (map document pipeline))) (.aggregate (collection db coll opts) ^List (map document pipeline)))
@ -102,7 +104,7 @@
(bulk-write db coll operations {})) (bulk-write db coll operations {}))
([^MongoDatabase db coll operations opts] ([^MongoDatabase db coll operations opts]
(let [opts' (->BulkWriteOptions opts)] (let [opts' (->BulkWriteOptions opts)]
(if-let [session (:session opts)] (if-let [session (or (:session opts) *session*)]
(.bulkWrite (collection db coll opts') ^ClientSession session ^List (map write-model operations)) (.bulkWrite (collection db coll opts') ^ClientSession session ^List (map write-model operations))
(.bulkWrite (collection db coll opts') (map write-model operations)))))) (.bulkWrite (collection db coll opts') (map write-model operations))))))
@ -130,7 +132,7 @@
(count-documents db coll q {})) (count-documents db coll q {}))
([^MongoDatabase db coll q opts] ([^MongoDatabase db coll q opts]
(let [opts' (->CountOptions opts)] (let [opts' (->CountOptions opts)]
(if-let [session (:session opts)] (if-let [session (or (:session opts) *session*)]
(.countDocuments (collection db coll opts) session (document q) opts') (.countDocuments (collection db coll opts) session (document q) opts')
(.countDocuments (collection db coll opts) (document q) opts'))))) (.countDocuments (collection db coll opts) (document q) opts')))))
@ -150,7 +152,7 @@
([^MongoDatabase db coll q] ([^MongoDatabase db coll q]
(delete-one db coll q {})) (delete-one db coll q {}))
([^MongoDatabase db coll q opts] ([^MongoDatabase db coll q opts]
(if-let [session (:session opts)] (if-let [session (or (:session opts) *session*)]
(.deleteOne (collection db coll opts) session (document q) (->DeleteOptions opts)) (.deleteOne (collection db coll opts) session (document q) (->DeleteOptions opts))
(.deleteOne (collection db coll opts) (document q) (->DeleteOptions opts))))) (.deleteOne (collection db coll opts) (document q) (->DeleteOptions opts)))))
@ -170,7 +172,7 @@
([^MongoDatabase db coll q] ([^MongoDatabase db coll q]
(delete-many db coll q {})) (delete-many db coll q {}))
([^MongoDatabase db coll q opts] ([^MongoDatabase db coll q opts]
(if-let [session (:session opts)] (if-let [session (or (:session opts) *session*)]
(.deleteMany (collection db coll opts) session (document q) (->DeleteOptions opts)) (.deleteMany (collection db coll opts) session (document q) (->DeleteOptions opts))
(.deleteMany (collection db coll opts) (document q) (->DeleteOptions opts))))) (.deleteMany (collection db coll opts) (document q) (->DeleteOptions opts)))))
@ -196,7 +198,8 @@
(find db coll q {})) (find db coll q {}))
([^MongoDatabase db coll q opts] ([^MongoDatabase db coll q opts]
(let [{:keys [limit skip sort projection ^ClientSession session keywordize? raw?] :or {keywordize? true raw? false}} opts] (let [{:keys [limit skip sort projection ^ClientSession session keywordize? raw?] :or {keywordize? true raw? false}} opts]
(let [it (cond-> (if session (let [^ClientSession session (or session *session*)
it (cond-> (if session
(.find (collection db coll opts) session (document q)) (.find (collection db coll opts) session (document q))
(.find (collection db coll opts) (document q))) (.find (collection db coll opts) (document q)))
limit (.limit limit) limit (.limit limit)
@ -241,6 +244,7 @@
(find-one-and-update db coll q update {})) (find-one-and-update db coll q update {}))
([^MongoDatabase db coll q update opts] ([^MongoDatabase db coll q update opts]
(let [{:keys [keywordize? ^ClientSession session] :or {keywordize? true}} opts (let [{:keys [keywordize? ^ClientSession session] :or {keywordize? true}} opts
^ClientSession session (or session *session*)
opts' (->FindOneAndUpdateOptions opts)] opts' (->FindOneAndUpdateOptions opts)]
(-> (if session (-> (if session
(.findOneAndUpdate (collection db coll opts) session (document q) (document update) opts') (.findOneAndUpdate (collection db coll opts) session (document q) (document update) opts')
@ -271,6 +275,7 @@
(find-one-and-replace db coll q doc {})) (find-one-and-replace db coll q doc {}))
([^MongoDatabase db coll q doc opts] ([^MongoDatabase db coll q doc opts]
(let [{:keys [keywordize? session] :or {keywordize? true}} opts (let [{:keys [keywordize? session] :or {keywordize? true}} opts
session (or session *session*)
opts' (->FindOneAndReplaceOptions opts)] opts' (->FindOneAndReplaceOptions opts)]
(-> (if session (-> (if session
(.findOneAndReplace (collection db coll opts) session (document q) (document doc) opts') (.findOneAndReplace (collection db coll opts) session (document q) (document doc) opts')
@ -297,7 +302,7 @@
(insert-one db coll doc {})) (insert-one db coll doc {}))
([^MongoDatabase db coll doc opts] ([^MongoDatabase db coll doc opts]
(let [opts' (->InsertOneOptions opts)] (let [opts' (->InsertOneOptions opts)]
(if-let [session (:session opts)] (if-let [session (or (:session opts) *session*)]
(.insertOne (collection db coll opts) session (document doc) opts') (.insertOne (collection db coll opts) session (document doc) opts')
(.insertOne (collection db coll opts) (document doc) opts'))))) (.insertOne (collection db coll opts) (document doc) opts')))))
@ -322,7 +327,7 @@
(insert-many db coll docs {})) (insert-many db coll docs {}))
([^MongoDatabase db coll docs opts] ([^MongoDatabase db coll docs opts]
(let [opts' (->InsertManyOptions opts)] (let [opts' (->InsertManyOptions opts)]
(if-let [^ClientSession session (:session opts)] (if-let [^ClientSession session (or (:session opts) *session*)]
(.insertMany (collection db coll opts) session ^List (map document docs) opts') (.insertMany (collection db coll opts) session ^List (map document docs) opts')
(.insertMany (collection db coll opts) ^List (map document docs) opts'))))) (.insertMany (collection db coll opts) ^List (map document docs) opts')))))
@ -346,7 +351,7 @@
([^MongoDatabase db coll q doc] ([^MongoDatabase db coll q doc]
(find-one-and-replace db coll q doc {})) (find-one-and-replace db coll q doc {}))
([^MongoDatabase db coll q doc opts] ([^MongoDatabase db coll q doc opts]
(if-let [^ClientSession session (:session opts)] (if-let [^ClientSession session (or (:session opts) *session*)]
(.replaceOne (collection db coll opts) session (document q) (document doc) (->ReplaceOptions opts)) (.replaceOne (collection db coll opts) session (document q) (document doc) (->ReplaceOptions opts))
(.replaceOne (collection db coll opts) (document q) (document doc) (->ReplaceOptions opts))))) (.replaceOne (collection db coll opts) (document q) (document doc) (->ReplaceOptions opts)))))
@ -370,7 +375,7 @@
([^MongoDatabase db coll q update] ([^MongoDatabase db coll q update]
(update-one db coll q update {})) (update-one db coll q update {}))
([^MongoDatabase db coll q update opts] ([^MongoDatabase db coll q update opts]
(if-let [^ClientSession session (:session opts)] (if-let [^ClientSession session (or (:session opts) *session*)]
(.updateOne (collection db coll opts) session (document q) (document update) (->UpdateOptions opts)) (.updateOne (collection db coll opts) session (document q) (document update) (->UpdateOptions opts))
(.updateOne (collection db coll opts) (document q) (document update) (->UpdateOptions opts))))) (.updateOne (collection db coll opts) (document q) (document update) (->UpdateOptions opts)))))
@ -394,7 +399,7 @@
([^MongoDatabase db coll q update] ([^MongoDatabase db coll q update]
(update-many db coll q update {})) (update-many db coll q update {}))
([^MongoDatabase db coll q update opts] ([^MongoDatabase db coll q update opts]
(if-let [^ClientSession session (:session opts)] (if-let [^ClientSession session (or (:session opts) *session*)]
(.updateMany (collection db coll opts) session (document q) (document update) (->UpdateOptions opts)) (.updateMany (collection db coll opts) session (document q) (document update) (->UpdateOptions opts))
(.updateMany (collection db coll opts) (document q) (document update) (->UpdateOptions opts))))) (.updateMany (collection db coll opts) (document q) (document update) (->UpdateOptions opts)))))

View file

@ -1,8 +1,9 @@
(ns mongo-driver-3.client-test (ns mongo-driver-3.client-test
(:require [clojure.test :refer :all] (:require [clojure.test :refer :all]
[mongo-driver-3.client :as mg] [mongo-driver-3.client :as mg]
[mongo-driver-3.collection :as mc]) [mongo-driver-3.collection :as mc]
(:import (com.mongodb.client MongoClient MongoDatabase MongoIterable ListCollectionsIterable) [mongo-driver-3.model :as m])
(:import (com.mongodb.client MongoClient MongoDatabase MongoIterable ListCollectionsIterable ClientSession)
(java.util UUID) (java.util UUID)
(com.mongodb ClientSessionOptions ReadConcern ReadPreference) (com.mongodb ClientSessionOptions ReadConcern ReadPreference)
(java.util.concurrent TimeUnit))) (java.util.concurrent TimeUnit)))
@ -91,6 +92,27 @@
(mc/insert-one db "test" {:a 2} {:session session}) (mc/insert-one db "test" {:a 2} {:session session})
(mc/count-documents db "test" {} {:session session})))))))) (mc/count-documents db "test" {} {:session session}))))))))
(deftest ^:integration test-with-implicit-transaction
(testing "passing"
(let [db (new-db @client)
_ (mc/create db "test")]
(is (= 2 (mg/with-implicit-transaction
{:client @client}
(fn []
(mc/insert-one db "test" {:a 1})
(mc/insert-one db "test" {:a 2})
(mc/count-documents db "test" {})))))))
(testing "failing"
(let [db (new-db @client)
_ (mc/create db "test")]
(is (= 0 (try (mg/with-implicit-transaction
{:client @client}
(fn []
(mc/insert-one db "test" {:a 1})
(mc/insert-one db "test" {nil 2})))
(catch Exception _ (mc/count-documents db "test" {}))))))))
(deftest ^:integration test-with-transaction (deftest ^:integration test-with-transaction
(testing "passing" (testing "passing"
(let [db (new-db @client) (let [db (new-db @client)