Last active
September 19, 2018 06:09
-
-
Save vvvvalvalval/9330ac436a8cc1424da1 to your computer and use it in GitHub Desktop.
Mocking datomic.Connection for fast in-memory testing
This file contains 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
(ns bs.utils.mock-connection | |
"Utilities for using Datomic" | |
(:require [datomic.api :as d]) | |
(:use clojure.repl clojure.pprint) | |
(:import (java.util.concurrent BlockingQueue LinkedBlockingDeque) | |
(datomic Connection))) | |
(defrecord MockConnection | |
[dbAtom, ^BlockingQueue txQueue] | |
Connection | |
(db [this] @(.dbAtom this)) | |
(transact [this tx-data] (doto (datomic.promise/settable-future) | |
(deliver (let [tx-res | |
(loop [] | |
(let [db-atom (.dbAtom this) | |
old-val @db-atom | |
tx-res (d/with old-val tx-data) | |
new-val (:db-after tx-res)] | |
(if (compare-and-set! db-atom old-val new-val) | |
tx-res | |
(recur)) | |
))] | |
(.add ^BlockingQueue (.txQueue this) tx-res) | |
tx-res)) | |
)) | |
(transactAsync [this tx-data] (.transact this tx-data)) | |
(gcStorage [this olderThan]) | |
(requestIndex [this]) | |
(release [this]) | |
(sync [this] (doto (datomic.promise/settable-future) | |
(deliver (.db this)))) | |
(syncExcise [this t] (.sync this)) | |
(syncIndex [this t] (.sync this)) | |
(syncSchema [this t] (.sync this)) | |
(sync [this t] (.sync this)) | |
(txReportQueue [this] (.txQueue this))) | |
(defn ^Connection mock-conn | |
"Creates a mocked version of datomic.Connection which uses db/with internally. | |
Only supports datomic.api/db, datomic.api/transact and datomic.api/transact-async operations. | |
Sync and housekeeping methods are implemented as noops. #log() is not supported." | |
[db] | |
(MockConnection. (atom db) (LinkedBlockingDeque.))) | |
(comment ;; How fast is it ? | |
(def mem-db (bs.dev/local-db)) ;; creates a mem db, loads the schema and some fixture data in it. Takes about 20ms on my dev laptop. | |
(time (dotimes [i 1000] | |
(let [conn (mock-conn mem-db)] | |
@(d/transact conn [{:db/id (d/tempid :db.part/user) | |
:bouser/firstName (str "Valentinnnnn_" i) | |
:bouser/lastName (str "Valentinnnnn_" i) | |
:bouser/level "bandsquare" | |
:bouser/email (str "val.vvalval" i "@gmail.com") | |
}])))) | |
;; "Elapsed time: 2027.881 msecs". So this is a x10 improvement. | |
;; the schema and fixture data are quite small (35 attributes, 103 datoms), so I expect this will get more compelling as the application grows. | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that with this implementation Exceptions will not be wrapped, unlike what is described in the Datomic documentation. So be careful of that if you're using this implementation for development.