From 5cad97c6172fd7f0e7ad964b0b0dfaf8459afee9 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Wed, 10 Jan 2024 20:22:28 +0800 Subject: [PATCH] feat: returns a deferred promise for logseq.db/transact! This enables callers to wait for the result. --- deps/db/src/logseq/db.cljs | 26 ++++++-- .../src/logseq/outliner/datascript.cljs | 6 +- .../src/logseq/outliner/transaction.cljc | 5 +- src/main/frontend/handler/editor.cljs | 64 ++++++++++--------- .../frontend/modules/outliner/pipeline.cljs | 15 ++++- src/main/frontend/worker/rtc/db_listener.cljs | 3 +- 6 files changed, 71 insertions(+), 48 deletions(-) diff --git a/deps/db/src/logseq/db.cljs b/deps/db/src/logseq/db.cljs index 3d54070dbf..aa0b8e1d86 100644 --- a/deps/db/src/logseq/db.cljs +++ b/deps/db/src/logseq/db.cljs @@ -5,16 +5,14 @@ [datascript.core :as d] [cljs-time.core :as t] [cljs-time.coerce :as tc] - [logseq.db.frontend.property :as db-property] - [logseq.db.frontend.property.util :as db-property-util] - [logseq.db.sqlite.util :as sqlite-util] [clojure.string :as string] [logseq.common.util :as common-util] [logseq.common.config :as common-config] [logseq.db.frontend.content :as db-content] [clojure.set :as set] [logseq.db.frontend.rules :as rules] - [logseq.db.frontend.entity-plus])) + [logseq.db.frontend.entity-plus] + [promesa.core :as p])) ;; Use it as an input argument for datalog queries (def block-attrs @@ -53,6 +51,14 @@ [f] (when f (reset! *transact-fn f))) +(defonce *request-id (atom 0)) +(defonce *request-id->response (atom {})) + +(defn get-deferred-response + [request-id] + (assert request-id "request-id shouldn't be empty") + (get @*request-id->response request-id)) + (defn transact! ([conn tx-data] (transact! conn tx-data nil)) @@ -63,8 +69,16 @@ ;; (prn :debug :transact) ;; (cljs.pprint/pprint tx-data) - (let [f (or @*transact-fn d/transact!)] - (f conn tx-data tx-meta)))))) + (let [f (or @*transact-fn d/transact!) + sync? (= f d/transact!) + request-id (swap! *request-id inc) + tx-meta' (if sync? tx-meta + (assoc tx-meta :request-id request-id)) + result (f conn tx-data tx-meta')] + (if sync? result + (let [resp (p/deferred)] + (swap! *request-id->response assoc request-id resp) + resp))))))) (defn build-default-pages-tx [] diff --git a/deps/outliner/src/logseq/outliner/datascript.cljs b/deps/outliner/src/logseq/outliner/datascript.cljs index ced15eb6f9..9f4365e750 100644 --- a/deps/outliner/src/logseq/outliner/datascript.cljs +++ b/deps/outliner/src/logseq/outliner/datascript.cljs @@ -75,7 +75,7 @@ txs)) (defn transact! - [txs tx-meta {:keys [repo conn unlinked-graph? after-transact-fn set-state-fn] :as opts}] + [txs tx-meta {:keys [repo conn unlinked-graph? set-state-fn]}] (let [db-based? (and repo (sqlite-util/db-based-graph? repo)) txs (map (fn [m] (if (map? m) @@ -100,9 +100,7 @@ ;; (cljs.pprint/pprint txs) (try - (let [tx-report (ldb/transact! conn txs (assoc tx-meta :outliner/transact? true))] - (when (fn? after-transact-fn) (after-transact-fn tx-report opts)) - tx-report) + (ldb/transact! conn txs (assoc tx-meta :outliner/transact? true)) (catch :default e (js/console.error e) (throw e)))))) diff --git a/deps/outliner/src/logseq/outliner/transaction.cljc b/deps/outliner/src/logseq/outliner/transaction.cljc index e9382ef15d..75f20cb3b0 100644 --- a/deps/outliner/src/logseq/outliner/transaction.cljc +++ b/deps/outliner/src/logseq/outliner/transaction.cljc @@ -55,7 +55,4 @@ (when (seq all-tx#) ;; If it's empty, do nothing (when-not (:nested-transaction? opts#) ; transact only for the whole transaction - (let [result# (logseq.outliner.datascript/transact! all-tx# (dissoc opts## :transact-opts) (:transact-opts opts##))] - {:tx-report result# - :tx-data all-tx# - :tx-meta tx-meta#}))))))))) + (logseq.outliner.datascript/transact! all-tx# (dissoc opts## :transact-opts) (:transact-opts opts##)))))))))) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 4133e4103e..6d680de242 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -268,40 +268,44 @@ ;; :block/uuid might be changed when backspace/delete ;; a block that has been refed (assoc :block/uuid (:block/uuid block))) - opts' (assoc opts :outliner-op :save-block)] - (let [original-block (db/entity (:db/id block)) - original-props (:block/properties original-block) - {:keys [tx-data]} - (ui-outliner-tx/transact! - opts' - (outliner-save-block! block') - ;; page properties changed - (when-let [page-name (and (:block/pre-block? block') - (not= original-props (:block/properties block')) - (some-> (:block/page block') :db/id (db-utils/pull) :block/name))] - (state/set-page-properties-changed! page-name))) - [original linked] (when-not (:insert-block? opts) - (let [original-block (some (fn [m] (and (map? m) (:block/link m) m)) tx-data) - link (:block/link original-block) - link' (if (and (map? link) (:db/id link)) - (db/entity (:db/id link)) - (db/entity link))] - [original-block link']))] + opts' (assoc opts :outliner-op :save-block) + original-block (db/entity (:db/id block)) + original-props (:block/properties original-block)] + (p/let [{:keys [tx-data] :as result} + (ui-outliner-tx/transact! + opts' + (outliner-save-block! block') + ;; page properties changed + (when-let [page-name (and (:block/pre-block? block') + (not= original-props (:block/properties block')) + (some-> (:block/page block') :db/id (db-utils/pull) :block/name))] + (state/set-page-properties-changed! page-name))) + [original linked] (when-not (:insert-block? opts) + (let [original-block (some (fn [m] (and (map? m) (:block/link m) m)) tx-data) + link (:block/link original-block) + link' (if (and (map? link) (:db/id link)) + (db/entity (:db/id link)) + (db/entity link))] + [original-block link']))] + + ;; FIXME move this to pipeline ;; Block has been tagged, so we need to edit the linked page now (when (and linked (= (:db/id (state/get-edit-block)) (:db/id original))) - (edit-block! linked :max nil {}))) + (edit-block! linked :max nil {})) - ;; file based graph only - ;; sanitized page name changed - (when-let [title (get-in block' [:block/properties :title])] - (if (string? title) - (when-let [old-page-name (:block/name (db/entity (:db/id (:block/page block'))))] - (when (and (:block/pre-block? block') - (not (string/blank? title)) - (not= (util/page-name-sanity-lc title) old-page-name)) - (state/pub-event! [:page/title-property-changed old-page-name title true]))) - (js/console.error (str "Title is not a string: " title)))))))) + ;; file based graph only + ;; sanitized page name changed + (when-let [title (get-in block' [:block/properties :title])] + (if (string? title) + (when-let [old-page-name (:block/name (db/entity (:db/id (:block/page block'))))] + (when (and (:block/pre-block? block') + (not (string/blank? title)) + (not= (util/page-name-sanity-lc title) old-page-name)) + (state/pub-event! [:page/title-property-changed old-page-name title true]))) + (js/console.error (str "Title is not a string: " title)))) + + result))))) ;; id: block dom id, "ls-block-counter-uuid" (defn- another-block-with-same-id-exists? diff --git a/src/main/frontend/modules/outliner/pipeline.cljs b/src/main/frontend/modules/outliner/pipeline.cljs index f772655498..817c2c90f1 100644 --- a/src/main/frontend/modules/outliner/pipeline.cljs +++ b/src/main/frontend/modules/outliner/pipeline.cljs @@ -9,7 +9,9 @@ [frontend.modules.editor.undo-redo :as undo-redo] [datascript.core :as d] [frontend.handler.ui :as ui-handler] - [frontend.handler.history :as history])) + [frontend.handler.history :as history] + [logseq.db :as ldb] + [promesa.core :as p])) (defn- reset-editing-block-content! [tx-data] @@ -61,12 +63,14 @@ (history/restore-app-state! app-state)) (defn invoke-hooks - [{:keys [tx-meta tx-data deleted-block-uuids affected-keys blocks] :as opts}] + [{:keys [request-id tx-meta tx-data deleted-block-uuids affected-keys blocks] :as opts}] (let [{:keys [from-disk? new-graph? local-tx? undo? redo?]} tx-meta repo (state/get-current-repo) tx-report {:tx-meta tx-meta :tx-data tx-data}] + (prn :debug :worker-response :request-id request-id) + (let [conn (db/get-db repo false) tx-report (d/transact! conn tx-data tx-meta)] (when local-tx? @@ -120,4 +124,9 @@ (= :block/uuid (:a datom)) (= (:v datom) deleting-block-id) (true? (:added datom)))) tx-data) ; editing-block was added back (could be undo or from remote sync) - (state/set-state! :ui/deleting-block nil))))) + (state/set-state! :ui/deleting-block nil))) + + (when-let [deferred (ldb/get-deferred-response request-id)] + (p/resolve! deferred {:tx-meta tx-meta + :tx-data tx-data}) + (swap! ldb/*request-id->response dissoc request-id)))) diff --git a/src/main/frontend/worker/rtc/db_listener.cljs b/src/main/frontend/worker/rtc/db_listener.cljs index 8c047d3bdb..e2e5d2334c 100644 --- a/src/main/frontend/worker/rtc/db_listener.cljs +++ b/src/main/frontend/worker/rtc/db_listener.cljs @@ -183,7 +183,8 @@ (when-not pipeline-replace? (let [data (pr-str (merge - {:repo repo + {:request-id (:request-id tx-meta) + :repo repo :search-indice search-indice :tx-data (:tx-data tx-report') :tx-meta tx-meta}