diff --git a/src/datascript/conn.cljc b/src/datascript/conn.cljc index ea169dfb..34da168d 100644 --- a/src/datascript/conn.cljc +++ b/src/datascript/conn.cljc @@ -89,21 +89,22 @@ (vreset! *report r) (:db-after r)))) #?(:clj - (when-some [storage (storage/storage @conn)] - (let [{db :db-after - datoms :tx-data} @*report - settings (set/settings (:eavt db)) - *atom (:atom conn) - tx-tail' (:tx-tail (swap! *atom update :tx-tail conj datoms))] - (if (> (transduce (map count) + 0 tx-tail') (:branching-factor settings)) - ;; overflow tail - (do - (storage/store-impl! db (storage/storage-adapter db) false) - (swap! *atom assoc - :tx-tail [] - :db-last-stored db)) - ;; just update tail - (storage/store-tail db tx-tail'))))) + (when-some [_ (storage/storage @conn)] + (let [{db :db-after + datoms :tx-data} @*report] + (when (seq datoms) + (let [settings (set/settings (:eavt db)) + *atom (:atom conn) + tx-tail' (:tx-tail (swap! *atom update :tx-tail conj datoms))] + (if (> (transduce (map count) + 0 tx-tail') (:branching-factor settings)) + ;; overflow tail + (do + (storage/store-impl! db (storage/storage-adapter db) false) + (swap! *atom assoc + :tx-tail [] + :db-last-stored db)) + ;; just update tail + (storage/store-tail db tx-tail'))))))) @*report)) (defn transact! diff --git a/test/datascript/test/storage.clj b/test/datascript/test/storage.clj index 1c4cdb40..c1a634ac 100644 --- a/test/datascript/test/storage.clj +++ b/test/datascript/test/storage.clj @@ -304,6 +304,38 @@ (let [conn''' (d/restore-conn storage)] (is (= @conn'' @conn'''))))))) +(deftest test-noop-transactions + (testing "No-op transactions should not trigger storage writes" + (let [storage (make-storage {:stats true}) + conn (d/create-conn {:name {:db/unique :db.unique/identity}} + {:storage storage})] + + (testing "empty tx-data" + (reset-stats storage) + (let [report (d/transact! conn [])] + (is (empty? (:tx-data report))) + (is (empty? @(:*writes storage))))) + + (let [report (d/transact! conn [[:db/add 1 :name "Alice"]])] + (is (seq (:tx-data report))) + (is (= 1 (count @(:*writes storage))))) + + (testing "adding existing fact" + (reset-stats storage) + (let [report (d/transact! conn [[:db/add 1 :name "Alice"]])] + (is (empty? (:tx-data report))) + (is (empty? @(:*writes storage))))) + + (let [report (d/transact! conn [[:db/retract 1 :name "Alice"]])] + (is (seq (:tx-data report))) + (is (= 1 (count @(:*writes storage))))) + + (testing "retracting non-existing fact" + (reset-stats storage) + (let [report (d/transact! conn [[:db/retract 1 :name "Alice"]])] + (is (empty? (:tx-data report))) + (is (empty? @(:*writes storage)))))))) + (defn stress-test [{:keys [time branching-factor ref-type] :or {time 10000 branching-factor 32