Skip to content

Commit 3f141af

Browse files
committed
Fix CLJS tail replay unique conflicts
1 parent f91fec5 commit 3f141af

2 files changed

Lines changed: 40 additions & 13 deletions

File tree

src/datascript/storage.cljs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,20 +158,25 @@
158158
:max-eid max-eid
159159
:max-tx max-tx})]
160160
(remember-db db)
161-
[db (mapv #(keep (fn [[e a v tx]]
162-
;; TODO: do we still need this?
163-
;; fix unique constraint
164-
(let [datoms (db/-datoms db :eavt e a v nil)
165-
datom-exists? (some (fn [datom] (= tx (:tx datom))) datoms)
166-
;; retracted tx < 0
167-
added? (> tx 0)]
168-
(when-not (and datom-exists? added?)
169-
(db/datom e a v tx))))%)
170-
tail)]))))
161+
[db (mapv #(mapv (fn [[e a v tx]] (db/datom e a v tx)) %) tail)]))))
162+
163+
(defn- db-with-tail-datoms [db datoms]
164+
(try
165+
(let [tx (:tx (first datoms))
166+
db' (assoc db :max-tx (dec tx))]
167+
(:db-after (db/transact-tx-data (db/->TxReport db' db' [] {} {}) datoms)))
168+
(catch :default _
169+
db)))
171170

172171
(defn db-with-tail [db tail]
173-
;; Ensures old cardinality/one datoms retracted
174-
(:db-after (db/transact-tx-data (db/->TxReport db db [] {} {}) (apply concat tail))))
172+
(reduce
173+
(fn [db datoms]
174+
(if (empty? datoms)
175+
db
176+
(as-> db %
177+
(db-with-tail-datoms % datoms)
178+
(assoc % :max-tx (:tx (first datoms))))))
179+
db tail))
175180

176181
(defn restore
177182
([storage]

test/datascript/test/storage.cljs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,29 @@
163163
(d/store db)
164164
(storage/store-tail db tail)
165165
(is (= [1772979061145]
166-
(mapv :v (d/datoms (d/restore storage) :avet :block/updated-at)))))))
166+
(mapv :v (d/datoms (d/restore storage) :avet :block/updated-at))))))
167+
168+
(testing "restore drops tail groups rejected by unique constraints"
169+
(let [schema {:block/uuid {:db/unique :db.unique/identity}
170+
:block/title {}}
171+
storage (make-storage {:stats true})
172+
db (-> (d/empty-db schema {:storage storage
173+
:branching-factor 32
174+
:ref-type :strong})
175+
(d/db-with [[:db/add 1 :block/uuid "u1"]]))
176+
tail [[(db/datom 2 :block/uuid "u1" 536870915 true)
177+
(db/datom 2 :block/title "Title" 536870915 true)]
178+
[(db/datom 3 :block/title "Later" 536870916 true)]]]
179+
(d/store db)
180+
(storage/store-tail db tail)
181+
(let [db' (d/restore storage)]
182+
(is (= [1]
183+
(mapv :e (d/datoms db' :avet :block/uuid "u1"))))
184+
(is (= []
185+
(mapv (juxt :e :a :v) (d/datoms db' :eavt 2))))
186+
(is (= [[3 :block/title "Later"]]
187+
(mapv (juxt :e :a :v) (d/datoms db' :eavt 3))))
188+
(is (= 536870916 (:max-tx db')))))))
167189

168190
;; Commented out test-gc test-file-storage tests and helpers b/c they are not implemented in cljs
169191

0 commit comments

Comments
 (0)