fix: db requests could be dropped if some requests not finished yet

pull/10793/head
Tienson Qin 2024-01-14 12:55:55 +08:00
parent 74a76f0365
commit b55e4e7380
5 changed files with 87 additions and 71 deletions

View File

@ -59,30 +59,47 @@
(defn get-deferred-response (defn get-deferred-response
[request-id] [request-id]
(get @*request-id->response request-id)) (:response (get @*request-id->response request-id)))
;; run the next request
(add-watch *request-id->response :loop-execute-requests
(fn [_ _ _ new]
(when-let [request-id (some->> (keys new)
sort
first)]
(when-let [callback (:callback (get new request-id))]
(callback)))))
(defn transact! (defn transact!
([conn tx-data] ([conn tx-data]
(transact! conn tx-data nil)) (transact! conn tx-data nil))
([conn tx-data tx-meta] ([conn tx-data tx-meta]
(let [tx-data (common-util/fast-remove-nils tx-data)] (let [tx-data (common-util/fast-remove-nils tx-data)
request-finished? (request-finished?)]
;; Ensure worker can handle the request sequentially (one by one) ;; Ensure worker can handle the request sequentially (one by one)
;; Because UI assumes that the in-memory db has all the data except the last one transaction ;; Because UI assumes that the in-memory db has all the data except the last one transaction
(when (and (seq tx-data) (request-finished?)) (when (seq tx-data)
;; (prn :debug :transact) ;; (prn :debug :transact)
;; (cljs.pprint/pprint tx-data) ;; (cljs.pprint/pprint tx-data)
(let [f (or @*transact-fn d/transact!) (let [f (or @*transact-fn d/transact!)
sync? (= f d/transact!) sync? (= f d/transact!)
request-id (swap! *request-id inc) request-id (when-not sync? (swap! *request-id inc))
tx-meta' (if sync? tx-meta tx-meta' (cond-> tx-meta
(assoc tx-meta :request-id request-id)) (not sync?)
result (f conn tx-data tx-meta')] (assoc :request-id request-id))]
(if sync? result (if sync?
(let [resp (p/deferred)] (f conn tx-data tx-meta')
(swap! *request-id->response assoc request-id resp) (let [resp (p/deferred)]
resp))))))) (when request-finished?
(f conn tx-data tx-meta'))
(let [value (if request-finished?
{:response resp}
{:response resp
:callback #(f conn tx-data tx-meta')})]
(swap! *request-id->response assoc request-id value))
resp)))))))
(defn build-default-pages-tx (defn build-default-pages-tx
[] []

View File

@ -99,12 +99,12 @@ Options available:
blocks [] blocks []
ast []}} ast []}}
(cond (contains? common-config/mldoc-support-formats format) (cond (contains? common-config/mldoc-support-formats format)
(extract/extract file content extract-options') (extract/extract file content extract-options')
(common-config/whiteboard? file) (common-config/whiteboard? file)
(extract/extract-whiteboard-edn file content extract-options') (extract/extract-whiteboard-edn file content extract-options')
:else nil) :else nil)
block-ids (map (fn [block] {:block/uuid (:block/uuid block)}) blocks) block-ids (map (fn [block] {:block/uuid (:block/uuid block)}) blocks)
delete-blocks (delete-blocks-fn @conn (first pages) file block-ids) delete-blocks (delete-blocks-fn @conn (first pages) file block-ids)
block-refs-ids (->> (mapcat :block/refs blocks) block-refs-ids (->> (mapcat :block/refs blocks)
@ -121,13 +121,12 @@ Options available:
:ast ast}) :ast ast})
tx (concat tx [(cond-> {:file/path file tx (concat tx [(cond-> {:file/path file
:file/content content} :file/content content}
new? new?
;; TODO: use file system timestamp? ;; TODO: use file system timestamp?
(assoc :file/created-at (common-util/time-ms)))]) (assoc :file/created-at (common-util/time-ms)))])
tx' (common-util/fast-remove-nils tx)
result (if skip-db-transact? result (if skip-db-transact?
tx' tx
(ldb/transact! conn tx' (select-keys options [:new-graph? :from-disk?])))] (ldb/transact! conn tx (select-keys options [:new-graph? :from-disk?])))]
{:tx result {:tx result
:ast ast}))) :ast ast})))

View File

@ -2828,7 +2828,7 @@
(save-current-block!) (save-current-block!)
(remove-block-own-order-list-type! block)) (remove-block-own-order-list-type! block))
(p/let [*edit-block-fn (atom nil) (p/let [*edit-block-fn (atom nil)
_ (delete-block! repo false :*edit-block-fn *edit-block-fn)] result (delete-block! repo false :*edit-block-fn *edit-block-fn)]
(when-let [f @*edit-block-fn] (when-let [f @*edit-block-fn]
(f)))))) (f))))))

View File

@ -952,13 +952,12 @@
;; db-worker -> UI ;; db-worker -> UI
(defmethod handle :db/sync-changes [[_ {:keys [request-id] :as data}]] (defmethod handle :db/sync-changes [[_ {:keys [request-id] :as data}]]
(when request-id ; request-id could be nil sometimes (let [repo (state/get-current-repo)]
(let [repo (state/get-current-repo)] (pipeline/invoke-hooks data)
(pipeline/invoke-hooks data)
(ipc/ipc :db-transact repo (pr-str (:tx-data data)) (pr-str (:tx-meta data))) (ipc/ipc :db-transact repo (pr-str (:tx-data data)) (pr-str (:tx-meta data)))
(state/pub-event! [:search/transact-data repo (:search-indice data)]) (state/pub-event! [:search/transact-data repo (:search-indice data)])
nil))) nil))
(defn run! (defn run!
[] []

View File

@ -40,60 +40,61 @@
(defn invoke-hooks (defn invoke-hooks
[{:keys [request-id 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}]
(when request-id ;; (prn :debug :request-id request-id)
(let [{:keys [from-disk? new-graph? local-tx? undo? redo?]} tx-meta (let [{:keys [from-disk? new-graph? local-tx? undo? redo?]} tx-meta
repo (state/get-current-repo) repo (state/get-current-repo)
tx-report {:tx-meta tx-meta tx-report {:tx-meta tx-meta
:tx-data tx-data}] :tx-data tx-data}]
(let [conn (db/get-db repo false) (let [conn (db/get-db repo false)
tx-report (d/transact! conn tx-data tx-meta)] tx-report (d/transact! conn tx-data tx-meta)]
(when local-tx? (when local-tx?
(let [tx-id (get-tx-id tx-report)] (let [tx-id (get-tx-id tx-report)]
(store-undo-data! (assoc opts :tx-id tx-id)))) (store-undo-data! (assoc opts :tx-id tx-id))))
(when-not (or undo? redo?) (when-not (or undo? redo?)
(update-current-tx-editor-cursor! tx-report))) (update-current-tx-editor-cursor! tx-report)))
(let [pages (set (keep #(when (= :block/name (:a %)) (:v %)) tx-data))] (let [pages (set (keep #(when (= :block/name (:a %)) (:v %)) tx-data))]
(when (seq pages) (when (seq pages)
(mark-pages-as-loaded! repo pages))) (mark-pages-as-loaded! repo pages)))
(when (= (:outliner-op tx-meta) :delete-page) (when (= (:outliner-op tx-meta) :delete-page)
(state/pub-event! [:page/deleted repo (:deleted-page tx-meta) (:file-path tx-meta)])) (state/pub-event! [:page/deleted repo (:deleted-page tx-meta) (:file-path tx-meta)]))
(when (= (:outliner-op tx-meta) :rename-page) (when (= (:outliner-op tx-meta) :rename-page)
(state/pub-event! [:page/renamed repo (:data tx-meta)])) (state/pub-event! [:page/renamed repo (:data tx-meta)]))
(if (or from-disk? new-graph?) (if (or from-disk? new-graph?)
(do (do
(react/clear-query-state!) (react/clear-query-state!)
(ui-handler/re-render-root!)) (ui-handler/re-render-root!))
(when-not (:graph/importing @state/state) (when-not (:graph/importing @state/state)
(react/refresh! repo tx-report affected-keys) (react/refresh! repo tx-report affected-keys)
(when-let [state (:ui/restore-cursor-state @state/state)] (when-let [state (:ui/restore-cursor-state @state/state)]
(when (or undo? redo?) (when (or undo? redo?)
(restore-cursor-and-app-state! state undo?) (restore-cursor-and-app-state! state undo?)
(state/set-state! :ui/restore-cursor-state nil))) (state/set-state! :ui/restore-cursor-state nil)))
(state/set-state! :editor/start-pos nil) (state/set-state! :editor/start-pos nil)
(when (and state/lsp-enabled? (when (and state/lsp-enabled?
(seq blocks) (seq blocks)
(<= (count blocks) 1000)) (<= (count blocks) 1000))
(state/pub-event! [:plugin/hook-db-tx (state/pub-event! [:plugin/hook-db-tx
{:blocks blocks {:blocks blocks
:deleted-block-uuids deleted-block-uuids :deleted-block-uuids deleted-block-uuids
:tx-data (:tx-data tx-report) :tx-data (:tx-data tx-report)
:tx-meta (:tx-meta tx-report)}])))) :tx-meta (:tx-meta tx-report)}]))))
(when-let [deleting-block-id (:ui/deleting-block @state/state)] (when-let [deleting-block-id (:ui/deleting-block @state/state)]
(when (some (fn [datom] (and (when (some (fn [datom] (and
(= :block/uuid (:a datom)) (= :block/uuid (:a datom))
(= (:v datom) deleting-block-id) (= (:v datom) deleting-block-id)
(true? (:added datom)))) tx-data) ; editing-block was added back (could be undo or from remote sync) (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 request-id
(when-let [deferred (ldb/get-deferred-response request-id)] (when-let [deferred (ldb/get-deferred-response request-id)]
(p/resolve! deferred {:tx-meta tx-meta (p/resolve! deferred {:tx-meta tx-meta
:tx-data tx-data}) :tx-data tx-data})