Skip to content

Instantly share code, notes, and snippets.

@stuarthalloway
Created September 10, 2020 15:14
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 stuarthalloway/57411ab4205e528d7adeba33cd3b57af to your computer and use it in GitHub Desktop.
Save stuarthalloway/57411ab4205e528d7adeba33cd3b57af to your computer and use it in GitHub Desktop.
;; good repro #0: problem statement
;; in n takes (tricks: translate domain words into Datomic words, be precise.)
;; 0. "Two datoms in transaction conflict" move an entity id to a reference entity take
;; 1. "Retracting an entity and adding an entity"
;; ...
;; 5. "Retracting a unique identity datom and asserting the same identity on another datom causes
;; "2 datoms in transaction conflict"
;; good repro #1: depend only on Datomic API
(require
'[datomic.api :as d])
(def uri "datomic:mem://test")
;; repro tactic #1: only show return values when somebody might care
(d/create-database uri)
(def conn (d/connect uri))
(def schema
[{:db/ident :test/id,
:db/valueType :db.type/string,
:db/cardinality :db.cardinality/one,
:db/unique :db.unique/identity}
{:db/ident :test/ref,
:db/valueType :db.type/ref,
:db/cardinality :db.cardinality/many}])
@(d/transact conn schema)
(def result @(d/transact conn [{:db/id "foo"
:test/id "foo"}]))
;; good repro #2: repros must be reproducible, capture eids
(def eid (get-in result [:tempids "foo"]))
;; repro tactic #2: switch from transact to with so you can try multiple speculative things
(def db (d/db conn))
(d/with db
[[:db/retract eid :test/id "foo"]
[:db/add eid :test/ref "temp"]
[:db/add "temp" :test/id "foo"]])
=> Execution error (Exceptions$IllegalArgumentExceptionInfo) at datomic.error/argd (error.clj:120).
:db.error/datoms-conflict Two datoms in the same transaction conflict
{:d1 [17592186045418 :test/id "foo" 13194139534315 false],
:d2 [17592186045418 :test/id "foo" 13194139534315 true]}
;; good repro #3: try to eliminate possibly irrelevant things (in this case test/ref)
(d/with db
[[:db/retract eid :test/id "foo"]
[:db/add "temp" :test/id "foo"]])
=> Execution error (Exceptions$IllegalArgumentExceptionInfo) at datomic.error/argd (error.clj:120).
:db.error/datoms-conflict Two datoms in the same transaction conflict
{:d1 [17592186045418 :test/id "foo" 13194139534315 false],
:d2 [17592186045418 :test/id "foo" 13194139534315 true]}
;; hone intuition -- how confusing would it be if a unique identifier was
;; allowed to refer different eids in a single transaction? Where would
;; "even more stuff" live after this tx?
(d/with db
[[:db/retract eid :test/id "foo"]
[:db/add "temp" :test/id "foo"]
{:db/id [:test/id "foo"]
:db/doc "even more stuff"}])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment