Skip to content

Instantly share code, notes, and snippets.

@thosmos
Forked from vvvvalvalval/mock-connection.clj
Created October 21, 2015 18:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thosmos/451bb59b0f14a5d82fc5 to your computer and use it in GitHub Desktop.
Save thosmos/451bb59b0f14a5d82fc5 to your computer and use it in GitHub Desktop.
Mocking datomic.Connection for fast in-memory testing
(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