From 910a76fee06f40e6907355304db122bffc57ea41 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Wed, 20 May 2026 11:31:06 +0800 Subject: [PATCH] fix: sync migration txs (#12687) * fix: sync migration txs * fix: repair missing migration built-ins --- src/main/frontend/worker/db_core.cljs | 87 +++++++++++++++- src/test/frontend/worker/db_core_test.cljs | 109 +++++++++++++++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/src/main/frontend/worker/db_core.cljs b/src/main/frontend/worker/db_core.cljs index b36821d311..52c0985b51 100644 --- a/src/main/frontend/worker/db_core.cljs +++ b/src/main/frontend/worker/db_core.cljs @@ -44,6 +44,7 @@ [logseq.db.common.view :as db-view] [logseq.db.frontend.class :as db-class] [logseq.db.frontend.entity-util :as entity-util] + [logseq.db.frontend.property :as db-property] [logseq.db.frontend.schema :as db-schema] [logseq.db.sqlite.create-graph :as sqlite-create-graph] [logseq.db.sqlite.export :as sqlite-export] @@ -407,6 +408,87 @@ {:persist-op? false :skip-validate-db? true})))) +(defn- handle-migrate-result-local-txs! + [repo migrate-result] + (doseq [tx-report (:upgrade-result-coll migrate-result)] + (db-sync/handle-local-tx! repo tx-report))) + +(def ^:private built-in-sync-repair-tx-id + #uuid "00000000-0000-4000-8000-652665286528") + +(def ^:private built-in-sync-repair-properties + [:logseq.property.repeat/repeat-type + :logseq.property.comments/blocks]) + +(def ^:private built-in-sync-repair-classes + [:logseq.class/Comments + :logseq.class/Comment]) + +;; Fixed so duplicate repair txs from multiple clients converge on the same datoms. +(def ^:private built-in-sync-repair-timestamp 0) + +(defn- stable-built-in-sync-repair-item + [order item] + (if (and (map? item) (:block/uuid item)) + (assoc item + :block/created-at built-in-sync-repair-timestamp + :block/updated-at built-in-sync-repair-timestamp + :block/order order) + item)) + +(defn- built-in-sync-repair-tx-data + [] + (let [properties built-in-sync-repair-properties + new-properties (->> (select-keys db-property/built-in-properties properties) + sqlite-create-graph/build-properties + (map (fn [b] (assoc b :logseq.property/built-in? true)))) + new-classes (->> (select-keys db-class/built-in-classes built-in-sync-repair-classes) + (#(sqlite-create-graph/build-initial-classes* % (zipmap properties properties))) + (map (fn [b] (assoc b :logseq.property/built-in? true)))) + new-class-idents (keep (fn [class] + (when-let [db-ident (:db/ident class)] + {:db/ident db-ident})) + new-classes) + tx-data (vec (concat new-class-idents new-properties new-classes)) + block-item-count (count (filter #(and (map? %) (:block/uuid %)) tx-data)) + orders (db-order/gen-n-keys block-item-count nil nil :max-key-atom (atom nil)) + *orders (atom orders)] + (mapv (fn [item] + (stable-built-in-sync-repair-item + (when (and (map? item) (:block/uuid item)) + (let [order (first @*orders)] + (swap! *orders rest) + order)) + item)) + tx-data))) + +(defn- enqueue-built-in-sync-repair! + [repo] + (when-not (client-op/get-local-tx-entry repo built-in-sync-repair-tx-id) + (let [{:keys [should-inc-pending?]} + (client-op/upsert-local-tx-entry! + repo + {:tx-id built-in-sync-repair-tx-id + :created-at 0 + :pending? true + :failed? false + :outliner-op :fix + :undo-redo :none + :forward-outliner-ops [] + :inverse-outliner-ops [] + :inferred-outliner-ops? false + :normalized-tx-data (built-in-sync-repair-tx-data) + :reversed-tx-data []})] + (when should-inc-pending? + (client-op/adjust-pending-local-tx-count! repo 1))))) + +(defn- maybe-enqueue-built-in-sync-repair! + [repo conn migrate-result initial-data-exists?] + (when (and (nil? migrate-result) + initial-data-exists? + (true? (:kv/value (d/entity @conn :logseq.kv/graph-remote?)))) + (enqueue-built-in-sync-repair! repo))) + (defn-