Skip to content

Commit fb014bc

Browse files
jxonastonsky
authored andcommitted
Skip -store on no-op transactions
Only call storage -store in transact! when the tx report has non-empty :tx-data. This avoids unnecessary writes for idempotent/no-effect transactions while preserving TxReport contents and listener semantics.
1 parent 7691362 commit fb014bc

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

src/datascript/conn.cljc

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,22 @@
8989
(vreset! *report r)
9090
(:db-after r))))
9191
#?(:clj
92-
(when-some [storage (storage/storage @conn)]
93-
(let [{db :db-after
94-
datoms :tx-data} @*report
95-
settings (set/settings (:eavt db))
96-
*atom (:atom conn)
97-
tx-tail' (:tx-tail (swap! *atom update :tx-tail conj datoms))]
98-
(if (> (transduce (map count) + 0 tx-tail') (:branching-factor settings))
99-
;; overflow tail
100-
(do
101-
(storage/store-impl! db (storage/storage-adapter db) false)
102-
(swap! *atom assoc
103-
:tx-tail []
104-
:db-last-stored db))
105-
;; just update tail
106-
(storage/store-tail db tx-tail')))))
92+
(when-some [_ (storage/storage @conn)]
93+
(let [{db :db-after
94+
datoms :tx-data} @*report]
95+
(when (seq datoms)
96+
(let [settings (set/settings (:eavt db))
97+
*atom (:atom conn)
98+
tx-tail' (:tx-tail (swap! *atom update :tx-tail conj datoms))]
99+
(if (> (transduce (map count) + 0 tx-tail') (:branching-factor settings))
100+
;; overflow tail
101+
(do
102+
(storage/store-impl! db (storage/storage-adapter db) false)
103+
(swap! *atom assoc
104+
:tx-tail []
105+
:db-last-stored db))
106+
;; just update tail
107+
(storage/store-tail db tx-tail')))))))
107108
@*report))
108109

109110
(defn transact!

test/datascript/test/storage.clj

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,38 @@
304304
(let [conn''' (d/restore-conn storage)]
305305
(is (= @conn'' @conn''')))))))
306306

307+
(deftest test-noop-transactions
308+
(testing "No-op transactions should not trigger storage writes"
309+
(let [storage (make-storage {:stats true})
310+
conn (d/create-conn {:name {:db/unique :db.unique/identity}}
311+
{:storage storage})]
312+
313+
(testing "empty tx-data"
314+
(reset-stats storage)
315+
(let [report (d/transact! conn [])]
316+
(is (empty? (:tx-data report)))
317+
(is (empty? @(:*writes storage)))))
318+
319+
(let [report (d/transact! conn [[:db/add 1 :name "Alice"]])]
320+
(is (seq (:tx-data report)))
321+
(is (= 1 (count @(:*writes storage)))))
322+
323+
(testing "adding existing fact"
324+
(reset-stats storage)
325+
(let [report (d/transact! conn [[:db/add 1 :name "Alice"]])]
326+
(is (empty? (:tx-data report)))
327+
(is (empty? @(:*writes storage)))))
328+
329+
(let [report (d/transact! conn [[:db/retract 1 :name "Alice"]])]
330+
(is (seq (:tx-data report)))
331+
(is (= 1 (count @(:*writes storage)))))
332+
333+
(testing "retracting non-existing fact"
334+
(reset-stats storage)
335+
(let [report (d/transact! conn [[:db/retract 1 :name "Alice"]])]
336+
(is (empty? (:tx-data report)))
337+
(is (empty? @(:*writes storage))))))))
338+
307339
(defn stress-test [{:keys [time branching-factor ref-type]
308340
:or {time 10000
309341
branching-factor 32

0 commit comments

Comments
 (0)