mirror of
https://github.com/logseq/logseq.git
synced 2026-05-16 17:02:34 +00:00
fix: retract children entities on server
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
(ns logseq.db-sync.worker.handler.sync
|
||||
(:require [clojure.string :as string]
|
||||
(:require [clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[datascript.core :as d]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.db :as ldb]
|
||||
@@ -296,10 +297,32 @@
|
||||
|
||||
(defn- sanitize-tx
|
||||
[db outliner-op tx-data]
|
||||
(if (= outliner-op :fix)
|
||||
(remove (fn [[_ id]]
|
||||
(nil? (d/entity db id))) tx-data)
|
||||
tx-data))
|
||||
(let [retract-op? (fn [item]
|
||||
(and (vector? item)
|
||||
(= 2 (count item))
|
||||
(contains? #{:db/retractEntity :db.fn/retractEntity} (first item))))
|
||||
->eid (fn [entity-ref]
|
||||
(some-> (d/entity db entity-ref) :db/id))
|
||||
retract-eids (->> tx-data
|
||||
(keep (fn [item]
|
||||
(when (retract-op? item)
|
||||
(->eid (second item)))))
|
||||
set)
|
||||
descendant-retract-eids (->> retract-eids
|
||||
(mapcat (fn [eid]
|
||||
(let [entity (d/entity db eid)]
|
||||
(when (:block/uuid entity)
|
||||
(ldb/get-block-full-children-ids db eid)))))
|
||||
(remove nil?)
|
||||
set)
|
||||
missing-retract-eids (sort (set/difference descendant-retract-eids retract-eids))
|
||||
tx-data' (cond-> (vec tx-data)
|
||||
(seq missing-retract-eids)
|
||||
(into (map (fn [eid] [:db/retractEntity eid]) missing-retract-eids)))]
|
||||
(if (= outliner-op :fix)
|
||||
(remove (fn [[_ id]]
|
||||
(nil? (d/entity db id))) tx-data')
|
||||
tx-data')))
|
||||
|
||||
(defn- apply-tx-entry!
|
||||
[conn {:keys [tx outliner-op]}]
|
||||
|
||||
@@ -234,6 +234,83 @@
|
||||
(is (nil? (:data response)))
|
||||
(is (= 2 @apply-calls)))))
|
||||
|
||||
(defn- seed-page-with-block-tree!
|
||||
[conn]
|
||||
(let [page-uuid (random-uuid)
|
||||
parent-uuid (random-uuid)
|
||||
child-a-uuid (random-uuid)
|
||||
child-b-uuid (random-uuid)
|
||||
now 1775549093572]
|
||||
(d/transact! conn [{:block/uuid page-uuid
|
||||
:block/name "sync-repro-page"
|
||||
:block/title "sync-repro-page"
|
||||
:block/created-at now
|
||||
:block/updated-at now}
|
||||
{:block/uuid parent-uuid
|
||||
:block/title "parent"
|
||||
:block/parent [:block/uuid page-uuid]
|
||||
:block/page [:block/uuid page-uuid]
|
||||
:block/order "a0"
|
||||
:block/created-at now
|
||||
:block/updated-at now}
|
||||
{:block/uuid child-a-uuid
|
||||
:block/title "child-a"
|
||||
:block/parent [:block/uuid parent-uuid]
|
||||
:block/page [:block/uuid page-uuid]
|
||||
:block/order "a1"
|
||||
:block/created-at now
|
||||
:block/updated-at now}
|
||||
{:block/uuid child-b-uuid
|
||||
:block/title "child-b"
|
||||
:block/parent [:block/uuid parent-uuid]
|
||||
:block/page [:block/uuid page-uuid]
|
||||
:block/order "a2"
|
||||
:block/created-at now
|
||||
:block/updated-at now}])
|
||||
{:page-uuid page-uuid
|
||||
:parent-uuid parent-uuid
|
||||
:child-a-uuid child-a-uuid
|
||||
:child-b-uuid child-b-uuid}))
|
||||
|
||||
(deftest tx-batch-stale-retract-block-includes-current-descendants-test
|
||||
(testing "stale block retract should still delete descendants attached in current db"
|
||||
(let [sql (test-sql/make-sql)
|
||||
conn (storage/open-conn sql)
|
||||
self #js {:sql sql
|
||||
:conn conn
|
||||
:schema-ready true}
|
||||
{:keys [parent-uuid child-a-uuid child-b-uuid]} (seed-page-with-block-tree! conn)
|
||||
t-before (storage/get-t sql)
|
||||
stale-delete-entry {:tx (protocol/tx->transit [[:db/retractEntity [:block/uuid parent-uuid]]])
|
||||
:outliner-op :delete-blocks}
|
||||
response (with-redefs [ws/broadcast! (fn [& _] nil)]
|
||||
(sync-handler/handle-tx-batch! self nil [stale-delete-entry] t-before))]
|
||||
(is (= "tx/batch/ok" (:type response)))
|
||||
(is (number? (:t response)))
|
||||
(is (nil? (d/entity @conn [:block/uuid parent-uuid])))
|
||||
(is (nil? (d/entity @conn [:block/uuid child-a-uuid])))
|
||||
(is (nil? (d/entity @conn [:block/uuid child-b-uuid]))))))
|
||||
|
||||
(deftest tx-batch-stale-retract-page-includes-current-page-tree-test
|
||||
(testing "stale page retract should still delete page tree to avoid orphan blocks"
|
||||
(let [sql (test-sql/make-sql)
|
||||
conn (storage/open-conn sql)
|
||||
self #js {:sql sql
|
||||
:conn conn
|
||||
:schema-ready true}
|
||||
{:keys [page-uuid parent-uuid child-a-uuid child-b-uuid]} (seed-page-with-block-tree! conn)
|
||||
t-before (storage/get-t sql)
|
||||
stale-delete-entry {:tx (protocol/tx->transit [[:db/retractEntity [:block/uuid page-uuid]]])
|
||||
:outliner-op :delete-page}
|
||||
response (with-redefs [ws/broadcast! (fn [& _] nil)]
|
||||
(sync-handler/handle-tx-batch! self nil [stale-delete-entry] t-before))]
|
||||
(is (= "tx/batch/ok" (:type response)))
|
||||
(is (number? (:t response)))
|
||||
(is (nil? (d/entity @conn [:block/uuid page-uuid])))
|
||||
(is (nil? (d/entity @conn [:block/uuid parent-uuid])))
|
||||
(is (nil? (d/entity @conn [:block/uuid child-a-uuid])))
|
||||
(is (nil? (d/entity @conn [:block/uuid child-b-uuid]))))))
|
||||
|
||||
(deftest sync-pull-is-blocked-when-graph-is-not-ready-for-use-test
|
||||
(async done
|
||||
(let [self #js {:env #js {"DB" :db}
|
||||
|
||||
Reference in New Issue
Block a user