fix: don't record local txs for remote graph

This commit is contained in:
Tienson Qin
2026-01-30 02:00:09 +08:00
parent a02d157cab
commit de1c58b02a
8 changed files with 71 additions and 87 deletions

View File

@@ -40,4 +40,5 @@ RTC won't start when major-schema-versions don't match"
:logseq.kv/graph-text-embedding-model-name {:doc "Graph's text-embedding model name"
:rtc {:rtc/ignore-entity-when-init-upload true
:rtc/ignore-entity-when-init-download true}}
:logseq.kv/graph-rtc-e2ee? {:doc "true if it's a rtc graph with E2EE enabled"})))
:logseq.kv/graph-rtc-e2ee? {:doc "true if it's a rtc graph with E2EE enabled"}
:logseq.kv/graph-remote? {:doc "true if it's a remote graph"})))

View File

@@ -222,7 +222,7 @@
(defn build-db-initial-data
"Builds tx of initial data for a new graph including key values, initial files,
built-in properties and built-in classes"
[config-content & {:keys [import-type graph-git-sha]}]
[config-content & {:keys [import-type graph-git-sha remote-graph?]}]
(assert (string? config-content))
(let [initial-data (cond->
[(sqlite-util/kv :logseq.kv/db-type "db")
@@ -236,9 +236,11 @@
(into (sqlite-util/import-tx import-type))
graph-git-sha
(conj (sqlite-util/kv :logseq.kv/graph-git-sha graph-git-sha))
remote-graph?
(conj (sqlite-util/kv :logseq.kv/graph-remote? remote-graph?))
true
(conj (sqlite-util/kv :logseq.kv/local-graph-uuid
(uuid (str "loc" (subs (str (common-uuid/gen-uuid)) 3))))))
(uuid (str "00000000" (subs (str (common-uuid/gen-uuid)) 8))))))
initial-files (build-initial-files config-content)
{properties-tx :tx :keys [properties]} (build-initial-properties)
db-ident->properties (zipmap (map :db/ident properties) properties)

View File

@@ -454,7 +454,8 @@
(invalid-graph-name-warning)
(do
(set-creating-db? true)
(p/let [repo (repo-handler/new-db! graph-name)]
(p/let [repo (repo-handler/new-db! graph-name
{:remote-graph? cloud?})]
(when cloud?
(->
(p/do

View File

@@ -134,12 +134,13 @@
(let [full-graph-name (string/lower-case (str config/db-version-prefix graph-name))]
(some #(= (some-> (:url %) string/lower-case) full-graph-name) (state/get-repos))))
(defn- create-db [full-graph-name {:keys [file-graph-import?]}]
(defn- create-db [full-graph-name {:keys [file-graph-import? remote-graph?]}]
(->
(p/let [config config/config-default-content
_ (persist-db/<new full-graph-name
(cond-> {:config config
:graph-git-sha config/revision}
:graph-git-sha config/revision
:remote-graph? remote-graph?}
file-graph-import? (assoc :import-type :file-graph)))
_ (start-repo-db-if-not-exists! full-graph-name)
_ (state/add-repo! {:url full-graph-name :root (config/get-local-dir full-graph-name)})

View File

@@ -289,8 +289,9 @@
(let [initial-tx-report (when (and (not initial-data-exists?) (not datoms))
(let [config (or config "")
initial-data (sqlite-create-graph/build-db-initial-data
config (select-keys opts [:import-type :graph-git-sha]))]
(ldb/transact! conn initial-data {:initial-db? true})))]
config (select-keys opts [:import-type :graph-git-sha :remote-graph?]))]
(ldb/transact! conn initial-data
{:initial-db? true})))]
(db-migrate/migrate conn)
(gc-sqlite-dbs! db client-ops-db conn {})

View File

@@ -426,6 +426,15 @@
(when-let [client (current-client repo)]
(broadcast-rtc-state! client)))))
(comment
(defn- clear-pending-txs!
[repo]
(when-let [conn (client-ops-conn repo)]
(let [tx-data (->> (d/datoms @conn :avet :db-sync/created-at)
(map (fn [d]
[:db/retractEntity (:e d)])))]
(d/transact! conn tx-data)))))
(defn get-lookup-id
[x]
(when (and (vector? x)
@@ -1030,12 +1039,11 @@
(flush-pending! repo current))))))))))))))))))
(defn handle-local-tx!
[repo {:keys [tx-data tx-meta] :as tx-report}]
[repo {:keys [tx-data tx-meta db-after] :as tx-report}]
(when (and (enabled?) (seq tx-data)
(not (:rtc-tx? tx-meta))
(:persist-op? tx-meta true)
;; (ldb/get-graph-rtc-uuid (:db-after tx-report))
)
(:kv/value (d/entity db-after :logseq.kv/graph-remote?)))
(enqueue-local-tx! repo tx-report)
(when-let [client @worker-state/*db-sync-client]
(when (= repo (:repo client))
@@ -1096,7 +1104,8 @@
(defn- set-graph-e2ee-enabled!
[repo]
(when-let [conn (worker-state/get-datascript-conn repo)]
(ldb/transact! conn [(ldb/kv :logseq.kv/graph-rtc-e2ee? true)])))
(ldb/transact! conn [(ldb/kv :logseq.kv/graph-remote? true)
(ldb/kv :logseq.kv/graph-rtc-e2ee? true)])))
(defn upload-graph!
[repo]

View File

@@ -32,6 +32,40 @@
[tx-data]
(boolean (some structural-tx-item? tx-data)))
(defn- resolve-entity-id
[db value]
(cond
(int? value) value
(vector? value) (d/entid db value)
:else nil))
(defn- tx-entity-ids
[db tx-data]
(->> tx-data
(keep (fn [item]
(cond
(vector? item)
(let [e (second item)]
(resolve-entity-id db e))
(d/datom? item)
(resolve-entity-id db (:e item))
(map? item)
(or (resolve-entity-id db (:db/id item))
(resolve-entity-id db [:block/uuid (:block/uuid item)]))
:else nil)))
(remove nil?)
set))
(defn- entities-exist?
[db tx-data]
(every? (fn [id]
(when id
(d/entity db id)))
(tx-entity-ids db tx-data)))
(defn- parent-cycle?
[ent]
(let [start (:block/uuid ent)]
@@ -47,75 +81,6 @@
true
(recur next-ent (conj seen next-uuid) (inc steps))))))))
(defn- db-issues
[db]
(let [ents (->> (d/q '[:find [?e ...]
:where
[?e :block/uuid]]
db)
(map (fn [e] (d/entity db e))))
uuid-required-ids (->> (concat
(d/q '[:find [?e ...]
:where
[?e :block/title]]
db)
(d/q '[:find [?e ...]
:where
[?e :block/page]]
db)
(d/q '[:find [?e ...]
:where
[?e :block/parent]]
db))
distinct)]
(concat
(for [e uuid-required-ids
:let [ent (d/entity db e)]
:when (nil? (:block/uuid ent))]
{:type :missing-uuid :e e})
(for [ent ents
:let [uuid (:block/uuid ent)
parent (:block/parent ent)]
:when (and (not (ldb/page? ent)) (nil? parent))]
{:type :missing-parent :uuid uuid})
(for [ent ents
:let [uuid (:block/uuid ent)
parent (:block/parent ent)]
:when (and (not (ldb/page? ent)) parent (nil? (:block/uuid parent)))]
{:type :missing-parent-ref :uuid uuid})
(for [ent ents
:let [uuid (:block/uuid ent)
page (:block/page ent)]
:when (and (not (ldb/page? ent)) (nil? page))]
{:type :missing-page :uuid uuid})
(for [ent ents
:let [uuid (:block/uuid ent)
page (:block/page ent)]
:when (and (not (ldb/page? ent)) page (not (ldb/page? page)))]
{:type :page-not-page :uuid uuid})
(for [ent ents
:let [uuid (:block/uuid ent)
parent (:block/parent ent)
page (:block/page ent)
expected-page (when parent
(if (ldb/page? parent) parent (:block/page parent)))]
:when (and (not (ldb/page? ent))
parent
page
expected-page
(not= (:block/uuid expected-page) (:block/uuid page)))]
{:type :page-mismatch :uuid uuid})
(for [ent ents
:let [uuid (:block/uuid ent)
parent (:block/parent ent)]
:when (and parent (= uuid (:block/uuid parent)))]
{:type :self-parent :uuid uuid})
(for [ent ents
:let [uuid (:block/uuid ent)]
:when (and (not (ldb/page? ent))
(parent-cycle? ent))]
{:type :cycle :uuid uuid}))))
(defn- issues-for-entity-ids
[db ids]
(let [id->ent (->> ids
@@ -211,7 +176,11 @@
[conn tx-data]
(try
(if-not (structural-tx? tx-data)
true
(if (entities-exist? @conn tx-data)
true
(do
(log/warn ::undo-redo-invalid {:reason :missing-entities})
false))
(let [db-before @conn
tx-report (d/with db-before tx-data)
db-after (:db-after tx-report)

View File

@@ -320,8 +320,8 @@
(testing "undo validation skips db-issues for non-structural tx-data"
(let [conn (db/get-db test-db false)
{:keys [child-uuid]} (seed-page-parent-child!)]
(with-redefs [frontend.worker.undo-redo/db-issues (fn [_]
(throw (js/Error. "db-issues called")))]
(with-redefs [undo-validate/issues-for-entity-ids (fn [_ _]
(throw (js/Error. "issues-for-entity-ids called")))]
(is (true? (undo-validate/valid-undo-redo-tx?
conn
[[:db/add [:block/uuid child-uuid] :block/title "child-updated"]])))))))
@@ -331,9 +331,9 @@
(let [conn (db/get-db test-db false)
{:keys [page-uuid child-uuid]} (seed-page-parent-child!)
calls (atom 0)]
(with-redefs [frontend.worker.undo-redo/issues-for-entity-ids (fn [_ _]
(swap! calls inc)
[])]
(with-redefs [undo-validate/issues-for-entity-ids (fn [_ _]
(swap! calls inc)
[])]
(is (true? (undo-validate/valid-undo-redo-tx?
conn
[[:db/add [:block/uuid child-uuid] :block/parent [:block/uuid page-uuid]]])))