fix: reversed datoms should be normalized too for rebase

This commit is contained in:
Tienson Qin
2026-04-10 14:49:54 +08:00
parent bf04d4cf5d
commit 32806264ce
3 changed files with 33 additions and 48 deletions

View File

@@ -141,16 +141,6 @@
tx-data)]
(concat recreated-block-retract-ops datoms-for-retracted-eids others end-retract-ops)))
(defn- collect-title-updated-entities
[tx-data]
(->> tx-data
(keep (fn [d]
(when (= (count d) 5)
(let [[e a _v _t added] d]
(when (and added (= :block/title a))
e)))))
set))
(defn- resolve-eid
[db-before db-after retract? e]
(if retract?
@@ -163,25 +153,19 @@
(or (= :db.type/ref (:db/valueType (d/entity db-after attr)))
(= :db.type/ref (:db/valueType (d/entity db-before attr)))))
(defn- normalize-datom-item
[db-after db-before title-updated-entities [e a v t added]]
(defn normalize-datom
[db-after db-before [e a v t added]]
(let [retract? (not added)
drop-retract?
(and retract?
(or (contains? #{:block/created-at :block/updated-at} a)
(and (= :block/title a)
(contains? title-updated-entities e))))]
(when-not drop-retract?
(let [e' (resolve-eid db-before db-after retract? e)
v' (if (and (integer? v)
(pos? v)
(ref-value-type? db-after db-before a))
(resolve-eid db-before db-after retract? v)
v)]
(when (and (some? e') (some? v'))
(if added
[:db/add e' a v' t]
[:db/retract e' a v' t]))))))
e' (resolve-eid db-before db-after retract? e)
v' (if (and (integer? v)
(pos? v)
(ref-value-type? db-after db-before a))
(resolve-eid db-before db-after retract? v)
v)]
(when (and (some? e') (some? v'))
(if added
[:db/add e' a v' t]
[:db/retract e' a v' t]))))
(defn- normalize-retract-entity-item
[db-before d]
@@ -192,20 +176,19 @@
[op e'])))
(defn- normalize-tx-item
[db-after db-before title-updated-entities d]
[db-after db-before d]
(case (count d)
5 (normalize-datom-item db-after db-before title-updated-entities d)
5 (normalize-datom db-after db-before d)
2 (normalize-retract-entity-item db-before d)
nil))
(defn normalize-tx-data
[db-after db-before tx-data]
(let [title-updated-entities (collect-title-updated-entities tx-data)]
(->> tx-data
remove-conflict-datoms
(replace-attr-retract-with-retract-entity db-after)
sort-datoms
(keep #(normalize-tx-item db-after db-before title-updated-entities %))
(remove-retract-entity-ref db-after)
reorder-retract-entity
distinct)))
(->> tx-data
remove-conflict-datoms
(replace-attr-retract-with-retract-entity db-after)
sort-datoms
(keep #(normalize-tx-item db-after db-before %))
(remove-retract-entity-ref db-after)
reorder-retract-entity
distinct))

View File

@@ -98,12 +98,13 @@
(declare replay-canonical-outliner-op!
invalid-rebase-op!)
(defn reverse-tx-data [_db-before db-after tx-data]
(defn reverse-tx-data [db-before db-after tx-data]
(->> tx-data
reverse
(keep (fn [[e a v t added]]
(when (and (some? a) (some? v) (some? t) (boolean? added))
[(if added :db/retract :db/add) e a v t])))
(let [reversed-datom (d/datom e a v t (not added))]
;; trick: reverse the order of `db-before` and `db-after`
(db-normalize/normalize-datom db-before db-after reversed-datom))))
(db-normalize/replace-attr-retract-with-retract-entity-v2 db-after)))
(defn normalize-rebased-pending-tx
@@ -1075,6 +1076,7 @@
[repo {:keys [tx-data db-after db-before] :as tx-report}]
(let [normalized (normalize-tx-data db-after db-before tx-data)
reversed-datoms (reverse-tx-data db-before db-after tx-data)]
;; (prn :debug :reversed-datoms reversed-datoms)
;; (prn :debug :enqueue-local-tx :tx-data)
;; (cljs.pprint/pprint tx-data)
;; (prn :debug :enqueue-local-tx :normalized)

View File

@@ -3617,13 +3617,13 @@
(d/transact! conn [[:db/add (:db/id child1) :block/title "same"]])
(let [pending-before (#'sync-apply/pending-txs test-repo)]
(is (= 1 (count pending-before)))
(#'sync-apply/apply-remote-tx!
test-repo
nil
[[:db/add (:db/id child1) :block/title "same"]])
(#'sync-apply/apply-remote-tx!
test-repo
nil
[[:db/add (:db/id child1) :block/title "same"]])
(let [pending-after (#'sync-apply/pending-txs test-repo)]
(is (empty? pending-after))
(is (nil? (:tx-id (first pending-after))))))))))))
(is (= 1 (count pending-after)))
(is (uuid? (:tx-id (first pending-after))))))))))))
(deftest rebase-later-tx-for-new-block-uses-lookup-ref-test
(testing "rebased tx after creating a block should use lookup ref instead of stale tempid"