浏览代码

Merge branch 'feat/db' into fix/multiple-tabs

Tienson Qin 6 月之前
父节点
当前提交
cdb7c17a8e

+ 1 - 1
deps/db/src/logseq/db.cljs

@@ -75,7 +75,7 @@
 
      ;; 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
-     (when (seq tx-data)
+     (when (or (seq tx-data) (:db-persist? tx-meta))
 
        ;; (prn :debug :transact :sync? (= d/transact! (or @*transact-fn d/transact!)) :tx-meta tx-meta)
        ;; (cljs.pprint/pprint tx-data)

+ 6 - 0
src/main/frontend/common/missionary.cljs

@@ -108,6 +108,12 @@
     (let [x (m/?> (m/relieve {} >in))]
       (m/amb x (do (m/? (m/sleep dur-ms)) (m/amb))))))
 
+(defn snapshot-of-flow
+  "Return a task. take first value from f.
+  can be understood as `deref` in missionary"
+  [f]
+  (m/reduce {} nil (m/eduction (take 1) f)))
+
 (defn- fail-case-default-handler
   [e]
   (when-not (instance? Cancelled e)

+ 3 - 3
src/main/frontend/components/journal.cljs

@@ -21,9 +21,9 @@
   []
   (-> (react/q (state/get-current-repo)
                [:frontend.worker.react/journals]
-               {:async-query-fn (fn []
-                                  (p/let [{:keys [data]} (views/<load-view-data nil {:journals? true})]
-                                    (remove nil? data)))}
+               {:query-fn (fn [_]
+                            (p/let [{:keys [data]} (views/<load-view-data nil {:journals? true})]
+                              (remove nil? data)))}
                nil)
       util/react))
 

+ 8 - 12
src/main/frontend/db/react.cljs

@@ -42,13 +42,12 @@
   (reset! query-state {}))
 
 (defn add-q!
-  [k query inputs result-atom transform-fn query-fn async-query-fn inputs-fn]
+  [k query inputs result-atom transform-fn query-fn inputs-fn]
   (swap! query-state assoc k {:query query
                               :inputs inputs
                               :result result-atom
                               :transform-fn transform-fn
                               :query-fn query-fn
-                              :async-query-fn async-query-fn
                               :inputs-fn inputs-fn})
   result-atom)
 
@@ -86,7 +85,7 @@
     (:result result)))
 
 (defn- <q-aux
-  [repo db query-fn async-query-fn inputs-fn k query inputs built-in-query?]
+  [repo db query-fn inputs-fn k query inputs built-in-query?]
   (let [kv? (and (vector? k) (= :kv (second k)))
         q (if util/node-test?
             (fn [query inputs] (apply d/q query db inputs))
@@ -97,11 +96,8 @@
                   (p/let [_ (p/delay 100)]
                     (q-f))
                   (q-f)))))]
-    (when (or query-fn async-query-fn query kv?)
+    (when (or query-fn query kv?)
       (cond
-        async-query-fn
-        (async-query-fn)
-
         query-fn
         (query-fn db nil)
 
@@ -119,7 +115,7 @@
         (q query nil)))))
 
 (defn q
-  [repo k {:keys [use-cache? transform-fn query-fn async-query-fn inputs-fn
+  [repo k {:keys [use-cache? transform-fn query-fn inputs-fn
                   disable-reactive? return-promise? built-in-query?]
            :or {use-cache? true
                 transform-fn identity}} query & inputs]
@@ -135,9 +131,9 @@
         (if (and use-cache? result-atom)
           result-atom
           (let [result-atom (or result-atom (atom nil))
-                p-or-value (<q-aux repo db query-fn async-query-fn inputs-fn k query inputs built-in-query?)]
+                p-or-value (<q-aux repo db query-fn inputs-fn k query inputs built-in-query?)]
             (when-not disable-reactive?
-              (add-q! k query inputs result-atom transform-fn query-fn async-query-fn inputs-fn))
+              (add-q! k query inputs result-atom transform-fn query-fn inputs-fn))
             (cond
               return-promise?
               p-or-value
@@ -169,9 +165,9 @@
         (ldb/get-page (conn/get-db) page)))))
 
 (defn- execute-query!
-  [graph db k {:keys [query inputs transform-fn query-fn async-query-fn inputs-fn result built-in-query?]
+  [graph db k {:keys [query inputs transform-fn query-fn inputs-fn result built-in-query?]
                :or {transform-fn identity}}]
-  (p/let [p-or-value (<q-aux graph db query-fn async-query-fn inputs-fn k query inputs built-in-query?)
+  (p/let [p-or-value (<q-aux graph db query-fn inputs-fn k query inputs built-in-query?)
           result' (transform-fn p-or-value)]
     (when-not (= result' result)
       (set-new-result! k result'))))

+ 6 - 0
src/main/frontend/flows.cljs

@@ -19,6 +19,8 @@
 (def ^:private current-login-user-validator (ma/validator current-login-user-schema))
 (def *current-login-user (atom nil :validator current-login-user-validator))
 
+(def *network-online? (atom nil))
+
 ;; Public Flows
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -42,3 +44,7 @@
             (fn dtor [] (.removeEventListener ^js js/document "visibilitychange" callback-fn)))))
        (m/eduction (dedupe))
        (m/relieve)))
+
+(def network-online-event-flow
+  (->> (m/watch *network-online?)
+       (m/eduction (filter true?))))

+ 24 - 3
src/main/frontend/handler/db_based/rtc_flows.cljs

@@ -98,7 +98,7 @@ conditions:
     (let [visibility (m/?< flows/document-visibility-state-flow)]
       (try
         (if (= "visible" visibility)
-          (let [rtc-lock (:rtc-lock (m/? (m/reduce {} nil (m/eduction (take 1) rtc-state-flow))))]
+          (let [rtc-lock (:rtc-lock (m/? (c.m/snapshot-of-flow rtc-state-flow)))]
             (if (not rtc-lock)
               :document-visible&rtc-not-running
               (m/amb)))
@@ -106,20 +106,41 @@ conditions:
         (catch Cancelled _
           (m/amb))))))
 
+(def ^:private network-online&rtc-not-running-flow
+  (m/ap
+    (let [online? (m/?< flows/network-online-event-flow)]
+      (try
+        (if online?
+          (let [rtc-lock (:rtc-lock (m/? (c.m/snapshot-of-flow rtc-state-flow)))]
+            (if (not rtc-lock)
+              :network-online&rtc-not-running
+              (m/amb)))
+          (m/amb))
+        (catch Cancelled _
+          (m/amb))))))
+
 (def trigger-start-rtc-flow
   (->>
-   [(m/eduction
+   [;; login-user changed
+    (m/eduction
      (keep (fn [user] (when (:email user) [:login])))
      flows/current-login-user-flow)
+    ;; repo changed
     (m/eduction
      (keep (fn [repo] (when repo [:graph-switch repo])))
      flows/current-repo-flow)
+    ;; trigger-rtc by somewhere else
     (m/eduction
      (keep (fn [repo] (when repo [:trigger-rtc repo])))
      (m/watch *rtc-start-trigger))
+    ;; document visibilitychange->true
+    (m/eduction
+     (map vector)
+     document-visible&rtc-not-running-flow)
+    ;; network online->true
     (m/eduction
      (map vector)
-     document-visible&rtc-not-running-flow)]
+     network-online&rtc-not-running-flow)]
    (apply c.m/mix)
    (m/eduction (filter (fn [_] (some? (state/get-auth-id-token)))))
    (c.m/debounce 200)))

+ 6 - 1
src/main/frontend/state.cljs

@@ -75,6 +75,7 @@
       :nfs/refreshing?                       nil
       :instrument/disabled?                  (storage/get "instrument-disabled")
       ;; TODO: how to detect the network reliably?
+      ;; NOTE: prefer to use flows/network-online-event-flow
       :network/online?         true
       :indexeddb/support?      true
       :me                      nil
@@ -1641,7 +1642,11 @@ Similar to re-frame subscriptions"
 
 (defn set-online!
   [value]
-  (set-state! :network/online? value))
+  (set-state! :network/online? value)
+  ;; to avoid watch whole big state atom,
+  ;; there's an atom flows/*network-online?,
+  ;; then we can use flows/network-online-event-flow
+  (reset! flows/*network-online? value))
 
 (defn get-plugins-slash-commands
   []

+ 1 - 3
src/main/frontend/worker/flows.cljs

@@ -5,9 +5,7 @@
 
 (def online-event-flow
   (->> (m/watch (get @worker-state/*state :thread-atom/online-event))
-       (m/eduction
-        (drop-while nil?)
-        (filter true?))))
+       (m/eduction (filter true?))))
 
 (comment
   ((m/reduce (fn [_ x] (prn :xxx x)) online-event-flow) prn prn))

+ 27 - 12
src/main/frontend/worker/pipeline.cljs

@@ -1,6 +1,7 @@
 (ns frontend.worker.pipeline
   "Pipeline work after transaction"
-  (:require [datascript.core :as d]
+  (:require [clojure.string :as string]
+            [datascript.core :as d]
             [frontend.worker.commands :as commands]
             [frontend.worker.file :as file]
             [frontend.worker.react :as worker-react]
@@ -177,7 +178,7 @@
      :logseq.property.user/email email}))
 
 (defn- add-created-by-ref-hook
-  [db-after tx-data tx-meta]
+  [db-before db-after tx-data tx-meta]
   (when (and (not (or (:undo? tx-meta) (:redo? tx-meta) (:rtc-tx? tx-meta)))
              (seq tx-data))
     (when-let [decoded-id-token (some-> (worker-state/get-id-token) worker-util/parse-jwt)]
@@ -188,24 +189,34 @@
             add-created-by-tx-data
             (keep
              (fn [datom]
-               (when (and (keyword-identical? :block/uuid (:a datom))
-                          (:added datom))
-                 (let [e (:e datom)
-                       ent (d/entity db-after e)]
-                   (when-not (:logseq.property/created-by-ref ent)
-                     [:db/add e :logseq.property/created-by-ref created-by-id]))))
+               (let [attr (:a datom)
+                     value (:v datom)
+                     e (:e datom)]
+                 (cond
+                   ;; add created-by for new-block
+                   (and (keyword-identical? :block/uuid attr)
+                        (:added datom))
+                   (let [ent (d/entity db-after e)]
+                     (when-not (:logseq.property/created-by-ref ent)
+                       [:db/add e :logseq.property/created-by-ref created-by-id]))
+
+                   ;; update created-by when block change from empty-block-title to non-empty
+                   (and (keyword-identical? :block/title attr)
+                        (not (string/blank? value))
+                        (string/blank? (:block/title (d/entity db-before e))))
+                   [:db/add e :logseq.property/created-by-ref created-by-id])))
              tx-data)]
         (cond->> add-created-by-tx-data
           (nil? created-by-ent) (cons created-by-block))))))
 
 (defn- compute-extra-tx-data
   [repo tx-report]
-  (let [{:keys [db-after tx-data tx-meta]} tx-report
+  (let [{:keys [db-before db-after tx-data tx-meta]} tx-report
         display-blocks-tx-data (add-missing-properties-to-typed-display-blocks db-after tx-data)
         commands-tx (when-not (or (:undo? tx-meta) (:redo? tx-meta) (:rtc-tx? tx-meta))
                       (commands/run-commands tx-report))
         insert-templates-tx (insert-tag-templates repo tx-report)
-        created-by-tx (add-created-by-ref-hook db-after tx-data tx-meta)]
+        created-by-tx (add-created-by-ref-hook db-before db-after tx-data tx-meta)]
     (concat display-blocks-tx-data commands-tx insert-templates-tx created-by-tx)))
 
 (defn- invoke-hooks-default
@@ -256,7 +267,9 @@
                                     (when (:block/uuid (d/entity db-after db-id))
                                       {:db/id db-id
                                        :block/tx-id tx-id}))) updated-blocks))))
-          tx-report' (ldb/transact! conn replace-tx {:pipeline-replace? true})
+          tx-report' (ldb/transact! conn replace-tx {:pipeline-replace? true
+                                                     ;; Ensure db persisted
+                                                     :db-persist? true})
           _ (validate-db! repo conn tx-report* tx-meta context)
           full-tx-data (concat (:tx-data tx-report*)
                                (:tx-data refs-tx-report)
@@ -264,7 +277,9 @@
           final-tx-report (assoc tx-report'
                                  :tx-data full-tx-data
                                  :tx-meta tx-meta
-                                 :db-before (:db-before tx-report))
+                                 :db-before (:db-before tx-report)
+                                 :db-after (or (:db-after tx-report')
+                                               (:db-after tx-report)))
           affected-query-keys (when-not (:importing? context)
                                 (worker-react/get-affected-queries-keys final-tx-report))]
       {:tx-report final-tx-report

+ 1 - 1
src/main/frontend/worker/rtc/core.cljs

@@ -503,7 +503,7 @@
 
 (defn new-task--get-debug-state
   []
-  (m/reduce {} nil (m/eduction (take 1) create-get-state-flow)))
+  (c.m/snapshot-of-flow create-get-state-flow))
 
 (defn new-task--upload-graph
   [token repo remote-graph-name]