mirror of
https://github.com/logseq/logseq.git
synced 2026-05-27 22:24:09 +00:00
fix: large-title rehydrate
Root cause: large-title rehydrate was reusing the remote tx’s original entity id. When that id was a string tempid, Datascript had already resolved it during remote apply, so rehydrate created a new invalid entity with only :block/title.
This commit is contained in:
@@ -37,6 +37,20 @@
|
||||
(string? (:asset-uuid value))
|
||||
(string? (:asset-type value))))
|
||||
|
||||
(defn- find-large-title-object-eid
|
||||
[db obj]
|
||||
(some (fn [datom]
|
||||
(when (= obj (:v datom))
|
||||
(:e datom)))
|
||||
(d/datoms db :avet large-title-object-attr)))
|
||||
|
||||
(defn- resolve-large-title-item-eid
|
||||
[db {:keys [e obj]}]
|
||||
(or (when (number? e)
|
||||
e)
|
||||
(some-> (d/entity db e) :db/id)
|
||||
(find-large-title-object-eid db obj)))
|
||||
|
||||
(defn asset-url
|
||||
[base graph-id asset-uuid asset-type]
|
||||
(str base "/assets/" graph-id "/" asset-uuid "." asset-type))
|
||||
@@ -160,12 +174,16 @@
|
||||
(fail-fast-f :db-sync/missing-field {:repo repo :field :aes-key}))]
|
||||
(p/all
|
||||
(mapv (fn [{:keys [e obj]}]
|
||||
(p/let [title (download-fn repo graph-id* obj aes-key*)]
|
||||
(ldb/transact! conn*
|
||||
[[:db/add e :block/title title]]
|
||||
{:rtc-tx? true
|
||||
:persist-op? false
|
||||
:op :large-title-rehydrate})))
|
||||
(let [eid (resolve-large-title-item-eid @conn* {:e e :obj obj})]
|
||||
(when-not eid
|
||||
(fail-fast-f :db-sync/large-title-entity-missing
|
||||
{:repo repo :e e :obj obj}))
|
||||
(p/let [title (download-fn repo graph-id* obj aes-key*)]
|
||||
(ldb/transact! conn*
|
||||
[[:db/add eid :block/title title]]
|
||||
{:rtc-tx? true
|
||||
:persist-op? false
|
||||
:op :large-title-rehydrate}))))
|
||||
items)))))))
|
||||
|
||||
(defn offload-large-titles-in-datoms-batch
|
||||
|
||||
@@ -510,7 +510,8 @@
|
||||
:ws-state (atom :open)}
|
||||
broadcasts (atom [])]
|
||||
(with-redefs [shared-service/broadcast-to-clients! (fn [topic payload]
|
||||
(swap! broadcasts conj {:topic topic :payload payload}))]
|
||||
(swap! broadcasts conj {:topic topic :payload payload}))
|
||||
db-sync/status (constantly {})]
|
||||
(#'db-sync/update-online-users! client [{:user-id "u1" :username "Alice"}])
|
||||
(#'db-sync/update-online-users! client [{:user-id "u1" :username "Alice"}])
|
||||
(is (= 1 (count @broadcasts)))
|
||||
@@ -774,7 +775,8 @@
|
||||
:inflight (atom [])
|
||||
:online-users (atom [])
|
||||
:ws-state (atom :open)}]
|
||||
(with-redefs [client-op/get-local-tx (constantly 0)]
|
||||
(with-redefs [client-op/get-local-tx (constantly 0)
|
||||
sync-handle-message/sync-counts (constantly {})]
|
||||
(with-redefs [sync-log-state/rtc-log (fn [type payload]
|
||||
(reset! *captured {:type type
|
||||
:payload payload}))]
|
||||
@@ -4881,6 +4883,55 @@
|
||||
(is (= "rehydrated-title" (:block/title block))))
|
||||
(p/finally done))))))))
|
||||
|
||||
(deftest rehydrate-large-title-tempid-test
|
||||
(testing "rehydrate resolves remote tx tempids to the applied entity"
|
||||
(async done
|
||||
(let [conn (db-test/create-conn-with-blocks
|
||||
{:pages-and-blocks
|
||||
[{:page {:block/title "tempid-rehydrate-page"}}]})
|
||||
page (db-test/find-page-by-title @conn "tempid-rehydrate-page")
|
||||
page-id (:db/id page)
|
||||
block-uuid (random-uuid)
|
||||
tempid (str block-uuid)
|
||||
obj {:asset-uuid "title-tempid" :asset-type "txt"}
|
||||
tx-data [[:db/add tempid :block/uuid block-uuid]
|
||||
[:db/add tempid :block/title ""]
|
||||
[:db/add tempid :block/page page-id]
|
||||
[:db/add tempid :block/parent page-id]
|
||||
[:db/add tempid :block/order "a0"]
|
||||
[:db/add tempid :block/created-at 1]
|
||||
[:db/add tempid :block/updated-at 1]
|
||||
[:db/add tempid :logseq.property.sync/large-title-object obj]]
|
||||
download-calls (atom [])
|
||||
download-fn (fn [_repo _graph-id obj* _aes-key]
|
||||
(swap! download-calls conj obj*)
|
||||
(p/resolved "rehydrated tempid title"))]
|
||||
(with-datascript-conns conn nil
|
||||
(fn []
|
||||
(d/transact! conn tx-data)
|
||||
(let [block-id (:db/id (d/entity @conn [:block/uuid block-uuid]))]
|
||||
(is (int? block-id))
|
||||
(-> (p/let [_ (sync-large-title/rehydrate-large-titles!
|
||||
test-repo
|
||||
{:tx-data tx-data
|
||||
:conn conn
|
||||
:graph-id "graph-1"
|
||||
:download-fn download-fn
|
||||
:aes-key nil
|
||||
:get-conn-f worker-state/get-datascript-conn
|
||||
:graph-e2ee?-f sync-crypt/graph-e2ee?
|
||||
:ensure-graph-aes-key-f sync-crypt/<ensure-graph-aes-key
|
||||
:fail-fast-f db-sync/fail-fast})
|
||||
block (d/entity @conn [:block/uuid block-uuid])
|
||||
tempid-ent (d/entity @conn tempid)]
|
||||
(is (= [obj] @download-calls))
|
||||
(is (= block-id (:db/id block)))
|
||||
(is (= "rehydrated tempid title" (:block/title block)))
|
||||
(is (nil? tempid-ent)))
|
||||
(p/catch (fn [e]
|
||||
(is false (str e))))
|
||||
(p/finally done)))))))))
|
||||
|
||||
(defn- apply-template-to-empty-target!
|
||||
[conn template-root-uuid empty-target-uuid]
|
||||
(let [template-root (d/entity @conn [:block/uuid template-root-uuid])
|
||||
|
||||
Reference in New Issue
Block a user