Просмотр исходного кода

Merge branch 'feat/db' into enhance/plugin-web

charlie 1 год назад
Родитель
Сommit
91ef984f7a

+ 2 - 2
.carve/ignore

@@ -80,11 +80,11 @@ frontend.ui/_emoji-init-data
 frontend.worker.rtc.op-mem-layer/_sync-loop-canceler
 frontend.worker.rtc.op-mem-layer/_sync-loop-canceler
 ;; Used by shadow.cljs
 ;; Used by shadow.cljs
 frontend.worker.db-worker/init
 frontend.worker.db-worker/init
-;; WIP fn, remove when it's ready
-frontend.worker.rtc.asset-sync/<loop-for-assets-sync
 ;; Future use?
 ;; Future use?
 frontend.worker.rtc.hash/hash-blocks
 frontend.worker.rtc.hash/hash-blocks
 ;; Repl fn
 ;; Repl fn
 frontend.rum/use-atom-in
 frontend.rum/use-atom-in
 ;; missionary utils
 ;; missionary utils
 frontend.common.missionary-util/<!
 frontend.common.missionary-util/<!
+;; Not sure why carve said it's unused...
+frontend.flows/current-repo-flow

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

@@ -3,22 +3,22 @@
    For shared file graph only fns, use logseq.graph-parser.db"
    For shared file graph only fns, use logseq.graph-parser.db"
   (:require [clojure.set :as set]
   (:require [clojure.set :as set]
             [clojure.string :as string]
             [clojure.string :as string]
+            [clojure.walk :as walk]
             [datascript.core :as d]
             [datascript.core :as d]
             [datascript.impl.entity :as de]
             [datascript.impl.entity :as de]
             [logseq.common.config :as common-config]
             [logseq.common.config :as common-config]
             [logseq.common.util :as common-util]
             [logseq.common.util :as common-util]
+            [logseq.common.util.namespace :as ns-util]
+            [logseq.common.util.page-ref :as page-ref]
             [logseq.common.uuid :as common-uuid]
             [logseq.common.uuid :as common-uuid]
             [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.delete-blocks :as delete-blocks] ;; Load entity extensions
             [logseq.db.frontend.delete-blocks :as delete-blocks] ;; Load entity extensions
-            [logseq.db.frontend.entity-plus]
+            [logseq.db.frontend.entity-plus :as entity-plus]
             [logseq.db.frontend.entity-util :as entity-util]
             [logseq.db.frontend.entity-util :as entity-util]
+            [logseq.db.frontend.property :as db-property]
             [logseq.db.frontend.rules :as rules]
             [logseq.db.frontend.rules :as rules]
             [logseq.db.sqlite.common-db :as sqlite-common-db]
             [logseq.db.sqlite.common-db :as sqlite-common-db]
-            [logseq.db.sqlite.util :as sqlite-util]
-            [logseq.db.frontend.property :as db-property]
-            [logseq.common.util.namespace :as ns-util]
-            [logseq.common.util.page-ref :as page-ref]
-            [clojure.walk :as walk])
+            [logseq.db.sqlite.util :as sqlite-util])
   (:refer-clojure :exclude [object?]))
   (:refer-clojure :exclude [object?]))
 
 
 (defonce *transact-fn (atom nil))
 (defonce *transact-fn (atom nil))
@@ -192,7 +192,7 @@
 
 
 (def get-first-page-by-name sqlite-common-db/get-first-page-by-name)
 (def get-first-page-by-name sqlite-common-db/get-first-page-by-name)
 
 
-(def db-based-graph? entity-util/db-based-graph?)
+(def db-based-graph? entity-plus/db-based-graph?)
 
 
 (defn page-exists?
 (defn page-exists?
   "Returns truthy value if page exists.
   "Returns truthy value if page exists.

+ 3 - 2
deps/db/src/logseq/db/frontend/content.cljs

@@ -4,7 +4,8 @@
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [datascript.core :as d]
             [datascript.core :as d]
             [logseq.common.util :as common-util]
             [logseq.common.util :as common-util]
-            [logseq.db.frontend.entity-util :as entity-util]))
+            [logseq.db.frontend.entity-util :as entity-util]
+            [logseq.db.frontend.entity-plus :as entity-plus]))
 
 
 ;; [[uuid]]
 ;; [[uuid]]
 (def id-ref-pattern
 (def id-ref-pattern
@@ -121,7 +122,7 @@
 (defn update-block-content
 (defn update-block-content
   "Replace `[[internal-id]]` with `[[page name]]`"
   "Replace `[[internal-id]]` with `[[page name]]`"
   [db item eid]
   [db item eid]
-  (if (entity-util/db-based-graph? db)
+  (if (entity-plus/db-based-graph? db)
     (if-let [content (:block/title item)]
     (if-let [content (:block/title item)]
       (let [refs (:block/refs (d/entity db eid))]
       (let [refs (:block/refs (d/entity db eid))]
         (assoc item :block/title (id-ref->title-ref content refs false)))
         (assoc item :block/title (id-ref->title-ref content refs false)))

+ 3 - 2
deps/db/src/logseq/db/frontend/delete_blocks.cljs

@@ -5,7 +5,8 @@
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [datascript.core :as d]
             [datascript.core :as d]
             [clojure.string :as string]
             [clojure.string :as string]
-            [logseq.db.frontend.entity-util :as entity-util]))
+            [logseq.db.frontend.entity-util :as entity-util]
+            [logseq.db.frontend.entity-plus :as entity-plus]))
 
 
 (defn- replace-ref-with-deleted-block-title
 (defn- replace-ref-with-deleted-block-title
   [block ref-raw-title]
   [block ref-raw-title]
@@ -57,7 +58,7 @@
     (when (seq retracted-block-ids)
     (when (seq retracted-block-ids)
       (let [retracted-blocks (map #(d/entity db %) retracted-block-ids)
       (let [retracted-blocks (map #(d/entity db %) retracted-block-ids)
             retracted-tx (build-retracted-tx retracted-blocks)
             retracted-tx (build-retracted-tx retracted-blocks)
-            macros-tx (when-not (entity-util/db-based-graph? db)
+            macros-tx (when-not (entity-plus/db-based-graph? db)
                         (mapcat (fn [b]
                         (mapcat (fn [b]
                                   ;; Only delete if last reference
                                   ;; Only delete if last reference
                                   (keep #(when (<= (count (:block/_macros (d/entity db (:db/id %))))
                                   (keep #(when (<= (count (:block/_macros (d/entity db (:db/id %))))

+ 73 - 14
deps/db/src/logseq/db/frontend/entity_plus.cljc

@@ -5,23 +5,80 @@
   ;; Disable clj linters since we don't support clj
   ;; Disable clj linters since we don't support clj
   #?(:clj {:clj-kondo/config {:linters {:unresolved-namespace {:level :off}
   #?(:clj {:clj-kondo/config {:linters {:unresolved-namespace {:level :off}
                                         :unresolved-symbol {:level :off}}}})
                                         :unresolved-symbol {:level :off}}}})
-  (:require [cljs.core]
-            #?(:org.babashka/nbb [datascript.db])
+  (:require #?(:org.babashka/nbb [datascript.db])
+            [cljs.core]
+            [datascript.core :as d]
             [datascript.impl.entity :as entity :refer [Entity]]
             [datascript.impl.entity :as entity :refer [Entity]]
-            [logseq.db.frontend.content :as db-content]
-            [logseq.db.frontend.property :as db-property]
-            [logseq.db.frontend.entity-util :as entity-util]
+            [frontend.common.missionary-util :as c.m]
+            [frontend.flows :as flows]
             [logseq.common.util.date-time :as date-time-util]
             [logseq.common.util.date-time :as date-time-util]
-            [datascript.core :as d]))
-
-(def db-based-graph? entity-util/db-based-graph?)
-
-(def lookup-entity @#'entity/lookup-entity)
+            [logseq.db.frontend.entity-util :as entity-util]
+            [logseq.db.frontend.property :as db-property]
+            [missionary.core :as m]))
+
+(def immutable-db-idents
+  "These db-ident entities are immutable,
+  it means `(db/entity :block/title)` always return same result"
+  #{:block/created-at :block/updated-at
+    :block/uuid :block/title :block/tags :block/name :block/format
+    :block/schema :block/path-refs :block/refs :block/tx-id :block/type
+    :block/page :block/parent :block/order :block/journal-day :block/closed-value-property
+    :block/link :block/marker :block/warning :block/collapsed? :block/deadline :block/scheduled :block/level
+    :block/pre-block? :block/heading-level
+
+    :block/_refs :logseq.property/_query
+
+    :block.temp/search? :block.temp/ast-title :block.temp/ast-body
+    :block.temp/fully-loaded? :block.temp/top? :block.temp/bottom?
+
+    :db/cardinality :db/ident :db/index :db/valueType
+
+    :logseq.kv/db-type
+
+    :logseq.property.node/display-type :logseq.property/icon
+    :logseq.property.asset/type :logseq.property.asset/checksum
+    :logseq.property/created-from-property
+
+    :logseq.class/Query :logseq.class/Journal :logseq.class/Cards :logseq.class/Task})
+
+(def ^:private lookup-entity @#'entity/lookup-entity)
+
+(def ^:private *seen-immutable-entities (volatile! {}))
+
+(defn reset-immutable-entities-cache!
+  []
+  (vreset! *seen-immutable-entities {}))
+
+(c.m/run-background-task
+ ::reset-immutable-entities-cache!
+ (m/reduce
+  (fn [_ repo]
+    (when (some? repo)
+      (prn :reset-immutable-entities-cache!)
+      (reset-immutable-entities-cache!)))
+  flows/current-repo-flow))
+
+(defn entity-memoized
+  [db eid]
+  (if (and (qualified-keyword? eid)
+           (contains? immutable-db-idents eid))
+    (if-let [e (find @*seen-immutable-entities eid)]
+      (val e)
+      (let [r (d/entity db eid)]
+        (vswap! *seen-immutable-entities assoc eid r)
+        r))
+    (d/entity db eid)))
+
+(defn db-based-graph?
+  "Whether the current graph is db-only"
+  [db]
+  (when db
+    (= "db" (:kv/value (entity-memoized db :logseq.kv/db-type)))))
 
 
 (defn- get-journal-title
 (defn- get-journal-title
   [db e]
   [db e]
   (date-time-util/int->journal-title (:block/journal-day e)
   (date-time-util/int->journal-title (:block/journal-day e)
-                                     (:logseq.property.journal/title-format (d/entity db :logseq.class/Journal))))
+                                     (:logseq.property.journal/title-format (entity-memoized db :logseq.class/Journal))))
 
 
 (defn- get-block-title
 (defn- get-block-title
   [^Entity e k default-value]
   [^Entity e k default-value]
@@ -36,7 +93,7 @@
          (let [result (lookup-entity e k default-value)
          (let [result (lookup-entity e k default-value)
                refs (:block/refs e)
                refs (:block/refs e)
                result' (if (and (string? result) refs)
                result' (if (and (string? result) refs)
-                         (db-content/id-ref->title-ref result refs search?)
+                         ((resolve 'logseq.db.frontend.content/id-ref->title-ref) result refs search?)
                          result)]
                          result)]
            (or result' default-value)))))))
            (or result' default-value)))))))
 
 
@@ -51,7 +108,7 @@
        result
        result
        ;; property default value
        ;; property default value
        (when (qualified-keyword? k)
        (when (qualified-keyword? k)
-         (when-let [property (d/entity db k)]
+         (when-let [property (entity-memoized db k)]
            (let [schema (lookup-entity property :block/schema nil)]
            (let [schema (lookup-entity property :block/schema nil)]
              (if (= :checkbox (:type schema))
              (if (= :checkbox (:type schema))
                (lookup-entity property :logseq.property/scalar-default-value nil)
                (lookup-entity property :logseq.property/scalar-default-value nil)
@@ -107,7 +164,9 @@
   [^js this]
   [^js this]
   (let [v @(.-cache this)
   (let [v @(.-cache this)
         v' (if (:block/title v)
         v' (if (:block/title v)
-             (assoc v :block/title (db-content/id-ref->title-ref (:block/title v) (:block/refs this) (:block.temp/search? this)))
+             (assoc v :block/title
+                    ((resolve 'logseq.db.frontend.content/id-ref->title-ref)
+                     (:block/title v) (:block/refs this) (:block.temp/search? this)))
              v)]
              v)]
     (concat (seq v')
     (concat (seq v')
             (seq (.-kv this)))))
             (seq (.-kv this)))))

+ 2 - 9
deps/db/src/logseq/db/frontend/entity_util.cljs

@@ -1,16 +1,9 @@
 (ns logseq.db.frontend.entity-util
 (ns logseq.db.frontend.entity-util
   "Lower level entity util fns used across db namespaces"
   "Lower level entity util fns used across db namespaces"
-  (:require [datascript.core :as d]
-            [clojure.string :as string]
+  (:require [clojure.string :as string]
             [datascript.impl.entity :as de])
             [datascript.impl.entity :as de])
   (:refer-clojure :exclude [object?]))
   (:refer-clojure :exclude [object?]))
 
 
-(defn db-based-graph?
-  "Whether the current graph is db-only"
-  [db]
-  (when db
-    (= "db" (:kv/value (d/entity db :logseq.kv/db-type)))))
-
 (defn- has-tag?
 (defn- has-tag?
   [entity tag-ident]
   [entity tag-ident]
   (let [tags (:block/tags entity)]
   (let [tags (:block/tags entity)]
@@ -92,4 +85,4 @@
                      :logseq.class/Journal :journal
                      :logseq.class/Journal :journal
                      :logseq.class/Whiteboard :whiteboard
                      :logseq.class/Whiteboard :whiteboard
                      :logseq.class/Page :page}]
                      :logseq.class/Page :page}]
-    (set (map #(ident->type (:db/ident %)) (:block/tags entity)))))
+    (set (map #(ident->type (:db/ident %)) (:block/tags entity)))))

+ 10 - 9
deps/db/src/logseq/db/sqlite/common_db.cljs

@@ -1,15 +1,16 @@
 (ns logseq.db.sqlite.common-db
 (ns logseq.db.sqlite.common-db
   "Common sqlite db fns for browser and node"
   "Common sqlite db fns for browser and node"
-  (:require [datascript.core :as d]
-            ["path" :as node-path]
+  (:require ["path" :as node-path]
+            [clojure.set :as set]
             [clojure.string :as string]
             [clojure.string :as string]
-            [logseq.db.sqlite.util :as sqlite-util]
-            [logseq.common.util.date-time :as date-time-util]
-            [logseq.common.util :as common-util]
+            [datascript.core :as d]
             [logseq.common.config :as common-config]
             [logseq.common.config :as common-config]
+            [logseq.common.util :as common-util]
+            [logseq.common.util.date-time :as date-time-util]
+            [logseq.db.frontend.entity-plus :as entity-plus]
             [logseq.db.frontend.entity-util :as entity-util]
             [logseq.db.frontend.entity-util :as entity-util]
-            [clojure.set :as set]
-            [logseq.db.frontend.order :as db-order]))
+            [logseq.db.frontend.order :as db-order]
+            [logseq.db.sqlite.util :as sqlite-util]))
 
 
 (defn- get-pages-by-name
 (defn- get-pages-by-name
   [db page-name]
   [db page-name]
@@ -81,7 +82,7 @@
 
 
 (defn- property-with-values
 (defn- property-with-values
   [db block]
   [db block]
-  (when (entity-util/db-based-graph? db)
+  (when (entity-plus/db-based-graph? db)
     (let [block (d/entity db (:db/id block))]
     (let [block (d/entity db (:db/id block))]
       (->> (:block/properties block)
       (->> (:block/properties block)
            vals
            vals
@@ -242,7 +243,7 @@
   "Returns current database schema and initial data.
   "Returns current database schema and initial data.
    NOTE: This fn is called by DB and file graphs"
    NOTE: This fn is called by DB and file graphs"
   [db]
   [db]
-  (let [db-graph? (entity-util/db-based-graph? db)
+  (let [db-graph? (entity-plus/db-based-graph? db)
         _ (when db-graph?
         _ (when db-graph?
             (reset! db-order/*max-key (db-order/get-max-order db)))
             (reset! db-order/*max-key (db-order/get-max-order db)))
         schema (:schema db)
         schema (:schema db)

+ 5 - 3
deps/db/src/logseq/db/test/helper.cljs

@@ -1,9 +1,10 @@
 (ns ^:node-only logseq.db.test.helper
 (ns ^:node-only logseq.db.test.helper
   "Main ns for providing test fns for DB graphs"
   "Main ns for providing test fns for DB graphs"
   (:require [datascript.core :as d]
   (:require [datascript.core :as d]
+            [logseq.db.frontend.entity-plus :as entity-plus]
+            [logseq.db.frontend.schema :as db-schema]
             [logseq.db.sqlite.build :as sqlite-build]
             [logseq.db.sqlite.build :as sqlite-build]
-            [logseq.db.sqlite.create-graph :as sqlite-create-graph]
-            [logseq.db.frontend.schema :as db-schema]))
+            [logseq.db.sqlite.create-graph :as sqlite-create-graph]))
 
 
 (defn find-block-by-content
 (defn find-block-by-content
   "Find first block by exact block string or by fuzzier regex"
   "Find first block by exact block string or by fuzzier regex"
@@ -43,6 +44,7 @@
   []
   []
   (let [conn (d/create-conn db-schema/schema-for-db-based-graph)
   (let [conn (d/create-conn db-schema/schema-for-db-based-graph)
         _ (d/transact! conn (sqlite-create-graph/build-db-initial-data "{}"))]
         _ (d/transact! conn (sqlite-create-graph/build-db-initial-data "{}"))]
+    (entity-plus/reset-immutable-entities-cache!)
     conn))
     conn))
 
 
 (defn create-conn-with-blocks
 (defn create-conn-with-blocks
@@ -50,4 +52,4 @@
   [opts]
   [opts]
   (let [conn (create-conn)
   (let [conn (create-conn)
         _ (sqlite-build/create-blocks conn opts)]
         _ (sqlite-build/create-blocks conn opts)]
-    conn))
+    conn))

+ 1 - 1
deps/outliner/src/logseq/outliner/property.cljs

@@ -439,7 +439,7 @@
 
 
 (defn- property-with-position?
 (defn- property-with-position?
   [db property-id block position]
   [db property-id block position]
-  (let [property (d/entity db property-id)
+  (let [property (entity-plus/entity-memoized db property-id)
         schema (:block/schema property)]
         schema (:block/schema property)]
     (and
     (and
      (= (:position schema) position)
      (= (:position schema) position)

+ 6 - 5
deps/outliner/test/logseq/outliner/validate_test.cljs

@@ -1,8 +1,9 @@
 (ns logseq.outliner.validate-test
 (ns logseq.outliner.validate-test
-  (:require [cljs.test :refer [deftest is are testing]]
+  (:require [cljs.test :refer [are deftest is testing]]
             [datascript.core :as d]
             [datascript.core :as d]
-            [logseq.outliner.validate :as outliner-validate]
-            [logseq.db.test.helper :as db-test]))
+            [logseq.db.frontend.entity-plus :as entity-plus]
+            [logseq.db.test.helper :as db-test]
+            [logseq.outliner.validate :as outliner-validate]))
 
 
 (deftest validate-block-title-unique-for-properties
 (deftest validate-block-title-unique-for-properties
   (let [conn (db-test/create-conn-with-blocks
   (let [conn (db-test/create-conn-with-blocks
@@ -99,8 +100,8 @@
       (is (thrown-with-msg?
       (is (thrown-with-msg?
             js/Error
             js/Error
             #"Can't change.*built-in"
             #"Can't change.*built-in"
-            (outliner-validate/validate-parent-property (d/entity @conn :logseq.class/Task)
-                                                        [(d/entity @conn :logseq.class/Cards)]))))))
+            (outliner-validate/validate-parent-property (entity-plus/entity-memoized @conn :logseq.class/Task)
+                                                        [(entity-plus/entity-memoized @conn :logseq.class/Cards)]))))))
 
 
 (deftest validate-tags-property
 (deftest validate-tags-property
   (let [conn (db-test/create-conn-with-blocks
   (let [conn (db-test/create-conn-with-blocks

+ 7 - 7
deps/publishing/src/logseq/publishing/db.cljs

@@ -1,17 +1,17 @@
 (ns logseq.publishing.db
 (ns logseq.publishing.db
   "Provides db fns and associated util fns for publishing"
   "Provides db fns and associated util fns for publishing"
-  (:require [datascript.core :as d]
-            [logseq.db.frontend.rules :as rules]
-            [clojure.set :as set]
+  (:require [clojure.set :as set]
             [clojure.string :as string]
             [clojure.string :as string]
-            [logseq.db.frontend.entity-util :as entity-util]
-            [logseq.db.frontend.malli-schema :as db-malli-schema]))
+            [datascript.core :as d]
+            [logseq.db.frontend.entity-plus :as entity-plus]
+            [logseq.db.frontend.malli-schema :as db-malli-schema]
+            [logseq.db.frontend.rules :as rules]))
 
 
 (defn ^:api get-area-block-asset-url
 (defn ^:api get-area-block-asset-url
   "Returns asset url for an area block used by pdf assets. This lives in this ns
   "Returns asset url for an area block used by pdf assets. This lives in this ns
   because it is used by this dep and needs to be independent from the frontend app"
   because it is used by this dep and needs to be independent from the frontend app"
   [db block page]
   [db block page]
-  (let [db-based? (entity-util/db-based-graph? db)]
+  (let [db-based? (entity-plus/db-based-graph? db)]
     (when-some [uuid' (:block/uuid block)]
     (when-some [uuid' (:block/uuid block)]
       (if db-based?
       (if db-based?
         (when-let [image (:logseq.property.pdf/hl-image block)]
         (when-let [image (:logseq.property.pdf/hl-image block)]
@@ -105,7 +105,7 @@
 
 
 (defn- hl-type-area-fn
 (defn- hl-type-area-fn
   [db]
   [db]
-  (if (entity-util/db-based-graph? db)
+  (if (entity-plus/db-based-graph? db)
     (fn [datom]
     (fn [datom]
       (and (= :logseq.property.pdf/hl-type (:a datom))
       (and (= :logseq.property.pdf/hl-type (:a datom))
            (= (keyword (:v datom)) :area)))
            (= (keyword (:v datom)) :area)))

+ 13 - 6
src/main/frontend/components/block.cljs

@@ -19,8 +19,8 @@
             [frontend.components.property.value :as pv]
             [frontend.components.property.value :as pv]
             [frontend.components.query :as query]
             [frontend.components.query :as query]
             [frontend.components.query.builder :as query-builder-component]
             [frontend.components.query.builder :as query-builder-component]
-            [frontend.components.svg :as svg]
             [frontend.components.select :as select]
             [frontend.components.select :as select]
+            [frontend.components.svg :as svg]
             [frontend.config :as config]
             [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
             [frontend.context.i18n :refer [t]]
             [frontend.date :as date]
             [frontend.date :as date]
@@ -78,6 +78,7 @@
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
             [logseq.db.frontend.content :as db-content]
             [logseq.db.frontend.content :as db-content]
+            [logseq.db.frontend.entity-plus :as entity-plus]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.mldoc :as gp-mldoc]
             [logseq.graph-parser.mldoc :as gp-mldoc]
             [logseq.graph-parser.text :as text]
             [logseq.graph-parser.text :as text]
@@ -2285,7 +2286,9 @@
          ;; highlight ref block (area)
          ;; highlight ref block (area)
          (when area? [(hl-ref)])
          (when area? [(hl-ref)])
 
 
-         (when (and (seq block-ast-title) (ldb/class-instance? (db/entity :logseq.class/Cards) block))
+         (when (and (seq block-ast-title) (ldb/class-instance?
+                                           (entity-plus/entity-memoized (db/get-db) :logseq.class/Cards)
+                                           block))
            [(ui/tooltip
            [(ui/tooltip
              (shui/button
              (shui/button
               {:variant :ghost
               {:variant :ghost
@@ -2302,7 +2305,8 @@
   (let [collapsed? (:collapsed? config)
   (let [collapsed? (:collapsed? config)
         block' (db/entity (:db/id block))
         block' (db/entity (:db/id block))
         node-display-type (:logseq.property.node/display-type block')
         node-display-type (:logseq.property.node/display-type block')
-        query? (ldb/class-instance? (db/entity :logseq.class/Query) block')
+        db (db/get-db)
+        query? (ldb/class-instance? (entity-plus/entity-memoized db :logseq.class/Query) block')
         query (:logseq.property/query block')
         query (:logseq.property/query block')
         advanced-query? (and query? (= :code node-display-type))]
         advanced-query? (and query? (= :code node-display-type))]
     (cond
     (cond
@@ -3278,7 +3282,8 @@
 (rum/defc query-property-cp < rum/reactive db-mixins/query
 (rum/defc query-property-cp < rum/reactive db-mixins/query
   [block config collapsed?]
   [block config collapsed?]
   (let [block (db/entity (:db/id block))
   (let [block (db/entity (:db/id block))
-        query? (ldb/class-instance? (db/entity :logseq.class/Query) block)]
+        db (db/get-db)
+        query? (ldb/class-instance? (entity-plus/entity-memoized db :logseq.class/Query) block)]
     (when (and query? (not collapsed?))
     (when (and query? (not collapsed?))
       (let [query-id (:db/id (:logseq.property/query block))
       (let [query-id (:db/id (:logseq.property/query block))
             query (some-> query-id db/sub-block)
             query (some-> query-id db/sub-block)
@@ -3497,7 +3502,7 @@
         (db-properties-cp config block {:in-block-container? true})])
         (db-properties-cp config block {:in-block-container? true})])
 
 
      (when (and db-based? (not collapsed?) (not (or table? property?))
      (when (and db-based? (not collapsed?) (not (or table? property?))
-                (ldb/class-instance? (db/entity :logseq.class/Query) block))
+                (ldb/class-instance? (entity-plus/entity-memoized (db/get-db) :logseq.class/Query) block))
        (let [query-block (:logseq.property/query (db/entity (:db/id block)))
        (let [query-block (:logseq.property/query (db/entity (:db/id block)))
              query-block (if query-block (db/sub-block (:db/id query-block)) query-block)
              query-block (if query-block (db/sub-block (:db/id query-block)) query-block)
              query (:block/title query-block)
              query (:block/title query-block)
@@ -3506,7 +3511,9 @@
          [:div {:style {:padding-left 42}}
          [:div {:style {:padding-left 42}}
           (query/custom-query (wrap-query-components (assoc config
           (query/custom-query (wrap-query-components (assoc config
                                                             :dsl-query? (not advanced-query?)
                                                             :dsl-query? (not advanced-query?)
-                                                            :cards? (ldb/class-instance? (db/entity :logseq.class/Cards) block)))
+                                                            :cards? (ldb/class-instance? (entity-plus/entity-memoized
+                                                                                          (db/get-db)
+                                                                                          :logseq.class/Cards) block)))
                               (if advanced-query? result {:builder nil
                               (if advanced-query? result {:builder nil
                                                           :query (query-builder-component/sanitize-q query)}))]))
                                                           :query (query-builder-component/sanitize-q query)}))]))
 
 

+ 3 - 4
src/main/frontend/components/property.cljs

@@ -2,7 +2,6 @@
   "Block properties management."
   "Block properties management."
   (:require [clojure.set :as set]
   (:require [clojure.set :as set]
             [clojure.string :as string]
             [clojure.string :as string]
-            [dommy.core :as d]
             [frontend.components.dnd :as dnd]
             [frontend.components.dnd :as dnd]
             [frontend.components.icon :as icon-component]
             [frontend.components.icon :as icon-component]
             [frontend.components.property.config :as property-config]
             [frontend.components.property.config :as property-config]
@@ -10,16 +9,16 @@
             [frontend.components.property.value :as pv]
             [frontend.components.property.value :as pv]
             [frontend.components.select :as select]
             [frontend.components.select :as select]
             [frontend.components.svg :as svg]
             [frontend.components.svg :as svg]
-            [frontend.handler.property.util :as pu]
             [frontend.config :as config]
             [frontend.config :as config]
             [frontend.db :as db]
             [frontend.db :as db]
-            [frontend.db.model :as db-model]
             [frontend.db-mixins :as db-mixins]
             [frontend.db-mixins :as db-mixins]
             [frontend.db.async :as db-async]
             [frontend.db.async :as db-async]
+            [frontend.db.model :as db-model]
             [frontend.handler.db-based.property :as db-property-handler]
             [frontend.handler.db-based.property :as db-property-handler]
+            [frontend.handler.editor :as editor-handler]
             [frontend.handler.notification :as notification]
             [frontend.handler.notification :as notification]
+            [frontend.handler.property.util :as pu]
             [frontend.handler.route :as route-handler]
             [frontend.handler.route :as route-handler]
-            [frontend.handler.editor :as editor-handler]
             [frontend.mixins :as mixins]
             [frontend.mixins :as mixins]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.state :as state]
             [frontend.state :as state]

+ 18 - 1
src/main/frontend/core.cljs

@@ -2,6 +2,7 @@
   "Entry ns for the mobile, browser and electron frontend apps"
   "Entry ns for the mobile, browser and electron frontend apps"
   {:dev/always true}
   {:dev/always true}
   (:require [frontend.common-keywords]
   (:require [frontend.common-keywords]
+            [frontend.common.schema-register :as sr]
             [frontend.components.plugins :as plugins]
             [frontend.components.plugins :as plugins]
             [frontend.config :as config]
             [frontend.config :as config]
             [frontend.fs.sync :as sync]
             [frontend.fs.sync :as sync]
@@ -11,7 +12,6 @@
             [frontend.log]
             [frontend.log]
             [frontend.page :as page]
             [frontend.page :as page]
             [frontend.routes :as routes]
             [frontend.routes :as routes]
-            [frontend.common.schema-register :as sr]
             [frontend.spec]
             [frontend.spec]
             [logseq.api]
             [logseq.api]
             [malli.dev.cljs :as md]
             [malli.dev.cljs :as md]
@@ -58,11 +58,28 @@
     (when config/dev?
     (when config/dev?
       (js/setTimeout #(sync/<sync-start) 1000))))
       (js/setTimeout #(sync/<sync-start) 1000))))
 
 
+(comment
+  (def d-entity-count (volatile! 0))
+  (def ident->count (volatile! {}))
+  (def time-sum (volatile! 0))
+  (defn- setup-entity-profile!
+    []
+    (let [origin-d-entity d/entity]
+      (set! d/entity (fn [& args]
+                       (let [{r :result time :time} (util/with-time (apply origin-d-entity args))
+                             k (last args)]
+                         (vswap! d-entity-count inc)
+                         (vswap! ident->count update k inc)
+                         (vswap! time-sum #(+ time %))
+                         (println @d-entity-count (:db/id r) k (get @ident->count k) @time-sum "ms")
+                         r))))))
+
 (defn ^:export init []
 (defn ^:export init []
   ;; init is called ONCE when the page loads
   ;; init is called ONCE when the page loads
   ;; this is called in the index.html and must be exported
   ;; this is called in the index.html and must be exported
   ;; so it is available even in :advanced release builds
   ;; so it is available even in :advanced release builds
 
 
+  ;; (setup-entity-profile!)
   (plugin-handler/setup!
   (plugin-handler/setup!
    #(handler/start! start)))
    #(handler/start! start)))
 
 

+ 12 - 3
src/main/frontend/db/rtc/debug_ui.cljs

@@ -3,6 +3,7 @@
   (:require [fipp.edn :as fipp]
   (:require [fipp.edn :as fipp]
             [frontend.common.missionary-util :as c.m]
             [frontend.common.missionary-util :as c.m]
             [frontend.db :as db]
             [frontend.db :as db]
+            [frontend.handler.db-based.rtc-flows :as rtc-flows]
             [frontend.handler.user :as user]
             [frontend.handler.user :as user]
             [frontend.persist-db.browser :as db-browser]
             [frontend.persist-db.browser :as db-browser]
             [frontend.state :as state]
             [frontend.state :as state]
@@ -15,7 +16,6 @@
             [rum.core :as rum]))
             [rum.core :as rum]))
 
 
 (defonce debug-state (:rtc/state @state/state))
 (defonce debug-state (:rtc/state @state/state))
-(defonce rtc-log-flow (m/watch (:rtc/log @state/state)))
 
 
 (defn- stop
 (defn- stop
   []
   []
@@ -37,7 +37,7 @@
                                          logs)]
                                          logs)]
                              (reset! (get state ::logs) logs*)
                              (reset! (get state ::logs) logs*)
                              logs*))
                              logs*))
-                         nil rtc-log-flow)
+                         nil rtc-flows/rtc-log-flow)
                         ::sub-logs)]
                         ::sub-logs)]
                    (reset! (get state ::sub-log-canceler) canceler)
                    (reset! (get state ::sub-log-canceler) canceler)
                    state))
                    state))
@@ -102,6 +102,7 @@
             :remote-graphs (:remote-graphs debug-state*)
             :remote-graphs (:remote-graphs debug-state*)
             :online-users (:online-users debug-state*)
             :online-users (:online-users debug-state*)
             :auto-push? (:auto-push? debug-state*)
             :auto-push? (:auto-push? debug-state*)
+            :remote-profile? (:remote-profile? debug-state*)
             :current-page (state/get-current-page)
             :current-page (state/get-current-page)
             :blocks-count (when-let [page (state/get-current-page)]
             :blocks-count (when-let [page (state/get-current-page)]
                             (count (:block/_page (db/get-page page))))}
                             (count (:block/_page (db/get-page page))))}
@@ -126,7 +127,15 @@
                               {:on-click
                               {:on-click
                                (fn []
                                (fn []
                                  (let [^object worker @db-browser/*worker]
                                  (let [^object worker @db-browser/*worker]
-                                   (.rtc-toggle-auto-push worker (state/get-current-repo))))})]
+                                   (.rtc-toggle-auto-push worker)))})]
+        [:div.mr-2 (ui/button (str "Toggle remote profile("
+                                   (if (:remote-profile? debug-state*)
+                                     "ON" "OFF")
+                                   ")")
+                              {:on-click
+                               (fn []
+                                 (let [^object worker @db-browser/*worker]
+                                   (.rtc-toggle-remote-profile worker)))})]
         [:div (shui/button
         [:div (shui/button
                {:variant :outline
                {:variant :outline
                 :class "text-red-rx-09 border-red-rx-08 hover:text-red-rx-10"
                 :class "text-red-rx-09 border-red-rx-08 hover:text-red-rx-10"

+ 2 - 1
src/main/frontend/extensions/fsrs.cljs

@@ -18,6 +18,7 @@
             [frontend.ui :as ui]
             [frontend.ui :as ui]
             [frontend.util :as util]
             [frontend.util :as util]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
+            [logseq.db.frontend.entity-plus :as entity-plus]
             [logseq.shui.ui :as shui]
             [logseq.shui.ui :as shui]
             [missionary.core :as m]
             [missionary.core :as m]
             [open-spaced-repetition.cljc-fsrs.core :as fsrs.core]
             [open-spaced-repetition.cljc-fsrs.core :as fsrs.core]
@@ -247,7 +248,7 @@
         all-cards (concat
         all-cards (concat
                    [{:db/id :global
                    [{:db/id :global
                      :block/title "All cards"}]
                      :block/title "All cards"}]
-                   (db-model/get-class-objects repo (:db/id (db/entity :logseq.class/Cards))))
+                   (db-model/get-class-objects repo (:db/id (entity-plus/entity-memoized (db/get-db) :logseq.class/Cards))))
         *block-ids (::block-ids state)
         *block-ids (::block-ids state)
         block-ids (rum/react *block-ids)
         block-ids (rum/react *block-ids)
         loading? (rum/react (::loading? state))
         loading? (rum/react (::loading? state))

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

@@ -0,0 +1,11 @@
+(ns frontend.flows
+  "This ns contains some event flows."
+  (:require [missionary.core :as m]))
+
+(def *current-repo (atom nil))
+
+(def current-repo-flow
+  "Like get-current-repo."
+  (m/eduction
+   (dedupe)
+   (m/watch *current-repo)))

+ 9 - 7
src/main/frontend/handler/editor.cljs

@@ -2,6 +2,7 @@
   (:require [clojure.set :as set]
   (:require [clojure.set :as set]
             [clojure.string :as string]
             [clojure.string :as string]
             [clojure.walk :as w]
             [clojure.walk :as w]
+            [datascript.core :as d]
             [dommy.core :as dom]
             [dommy.core :as dom]
             [frontend.commands :as commands]
             [frontend.commands :as commands]
             [frontend.config :as config]
             [frontend.config :as config]
@@ -54,18 +55,18 @@
             [logseq.common.util.block-ref :as block-ref]
             [logseq.common.util.block-ref :as block-ref]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
-            [logseq.db.frontend.schema :as db-schema]
+            [logseq.db.frontend.entity-plus :as entity-plus]
             [logseq.db.frontend.property :as db-property]
             [logseq.db.frontend.property :as db-property]
+            [logseq.db.frontend.schema :as db-schema]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.mldoc :as gp-mldoc]
             [logseq.graph-parser.mldoc :as gp-mldoc]
             [logseq.graph-parser.property :as gp-property]
             [logseq.graph-parser.property :as gp-property]
             [logseq.graph-parser.text :as text]
             [logseq.graph-parser.text :as text]
             [logseq.graph-parser.utf8 :as utf8]
             [logseq.graph-parser.utf8 :as utf8]
             [logseq.outliner.core :as outliner-core]
             [logseq.outliner.core :as outliner-core]
-            [promesa.core :as p]
-            [rum.core :as rum]
             [logseq.outliner.property :as outliner-property]
             [logseq.outliner.property :as outliner-property]
-            [datascript.core :as d]))
+            [promesa.core :as p]
+            [rum.core :as rum]))
 
 
 ;; FIXME: should support multiple images concurrently uploading
 ;; FIXME: should support multiple images concurrently uploading
 
 
@@ -3457,15 +3458,16 @@
 (defn- db-collapsable?
 (defn- db-collapsable?
   [block]
   [block]
   (let [class-properties (:classes-properties (outliner-property/get-block-classes-properties (db/get-db) (:db/id block)))
   (let [class-properties (:classes-properties (outliner-property/get-block-classes-properties (db/get-db) (:db/id block)))
-        properties (->> (map :a (d/datoms (db/get-db) :eavt (:db/id block)))
-                        (map db/entity)
+        db (db/get-db)
+        properties (->> (map :a (d/datoms db :eavt (:db/id block)))
+                        (map (partial entity-plus/entity-memoized db))
                         (concat class-properties)
                         (concat class-properties)
                         (remove (fn [e] (db-property/db-attribute-properties (:db/ident e))))
                         (remove (fn [e] (db-property/db-attribute-properties (:db/ident e))))
                         (remove outliner-property/property-with-other-position?)
                         (remove outliner-property/property-with-other-position?)
                         (remove (fn [e] (:hide? (:block/schema e))))
                         (remove (fn [e] (:hide? (:block/schema e))))
                         (remove nil?))]
                         (remove nil?))]
     (or (seq properties)
     (or (seq properties)
-        (ldb/class-instance? (db/entity :logseq.class/Query) block))))
+        (ldb/class-instance? (entity-plus/entity-memoized db :logseq.class/Query) block))))
 
 
 (defn collapsable?
 (defn collapsable?
   ([block-id]
   ([block-id]

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

@@ -11,6 +11,7 @@
             [electron.ipc :as ipc]
             [electron.ipc :as ipc]
             [frontend.db.conn-state :as db-conn-state]
             [frontend.db.conn-state :as db-conn-state]
             [frontend.db.transact :as db-transact]
             [frontend.db.transact :as db-transact]
+            [frontend.flows :as flows]
             [frontend.mobile.util :as mobile-util]
             [frontend.mobile.util :as mobile-util]
             [frontend.rum :as r]
             [frontend.rum :as r]
             [frontend.spec.storage :as storage-spec]
             [frontend.spec.storage :as storage-spec]
@@ -21,6 +22,7 @@
             [goog.object :as gobj]
             [goog.object :as gobj]
             [logseq.common.config :as common-config]
             [logseq.common.config :as common-config]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
+            [logseq.db.frontend.entity-plus :as entity-plus]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.shui.dialog.core :as shui-dialog]
             [logseq.shui.dialog.core :as shui-dialog]
             [logseq.shui.ui :as shui]
             [logseq.shui.ui :as shui]
@@ -599,7 +601,7 @@ should be done through this fn in order to get global config and config defaults
   (let [repo (get-current-repo)]
   (let [repo (get-current-repo)]
     (if (sqlite-util/db-based-graph? repo)
     (if (sqlite-util/db-based-graph? repo)
       (when-let [conn (db-conn-state/get-conn repo)]
       (when-let [conn (db-conn-state/get-conn repo)]
-        (get (d/entity @conn :logseq.class/Journal)
+        (get (entity-plus/entity-memoized @conn :logseq.class/Journal)
              :logseq.property.journal/title-format
              :logseq.property.journal/title-format
              "MMM do, yyyy"))
              "MMM do, yyyy"))
       (common-config/get-date-formatter (get-config)))))
       (common-config/get-date-formatter (get-config)))))
@@ -978,6 +980,7 @@ Similar to re-frame subscriptions"
 (defn set-current-repo!
 (defn set-current-repo!
   [repo]
   [repo]
   (swap! state assoc :git/current-repo repo)
   (swap! state assoc :git/current-repo repo)
+  (reset! flows/*current-repo repo)
   (if repo
   (if repo
     (storage/set :git/current-repo repo)
     (storage/set :git/current-repo repo)
     (storage/remove :git/current-repo))
     (storage/remove :git/current-repo))

+ 4 - 0
src/main/frontend/worker/db_worker.cljs

@@ -755,6 +755,10 @@
    [this]
    [this]
    (rtc-core/rtc-toggle-auto-push))
    (rtc-core/rtc-toggle-auto-push))
 
 
+  (rtc-toggle-remote-profile
+   [this]
+   (rtc-core/rtc-toggle-remote-profile))
+
   (rtc-grant-graph-access
   (rtc-grant-graph-access
    [this token graph-uuid target-user-uuids-str target-user-emails-str]
    [this token graph-uuid target-user-uuids-str target-user-emails-str]
    (let [target-user-uuids (ldb/read-transit-str target-user-uuids-str)
    (let [target-user-uuids (ldb/read-transit-str target-user-uuids-str)

+ 5 - 4
src/main/frontend/worker/handler/page/db_based/page.cljs

@@ -7,15 +7,16 @@
             [logseq.common.util.namespace :as ns-util]
             [logseq.common.util.namespace :as ns-util]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
             [logseq.db.frontend.class :as db-class]
             [logseq.db.frontend.class :as db-class]
+            [logseq.db.frontend.entity-plus :as entity-plus]
+            [logseq.db.frontend.entity-util :as entity-util]
+            [logseq.db.frontend.malli-schema :as db-malli-schema]
             [logseq.db.frontend.order :as db-order]
             [logseq.db.frontend.order :as db-order]
             [logseq.db.frontend.property.build :as db-property-build]
             [logseq.db.frontend.property.build :as db-property-build]
             [logseq.db.frontend.property.util :as db-property-util]
             [logseq.db.frontend.property.util :as db-property-util]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.block :as gp-block]
             [logseq.graph-parser.text :as text]
             [logseq.graph-parser.text :as text]
-            [logseq.outliner.validate :as outliner-validate]
-            [logseq.db.frontend.entity-util :as entity-util]
-            [logseq.db.frontend.malli-schema :as db-malli-schema]))
+            [logseq.outliner.validate :as outliner-validate]))
 
 
 (defn- build-page-tx [conn properties page {:keys [whiteboard? class? tags]}]
 (defn- build-page-tx [conn properties page {:keys [whiteboard? class? tags]}]
   (when (:block/uuid page)
   (when (:block/uuid page)
@@ -168,7 +169,7 @@
            skip-existing-page-check? false}
            skip-existing-page-check? false}
     :as options}]
     :as options}]
   (let [db @conn
   (let [db @conn
-        date-formatter (:logseq.property.journal/title-format (d/entity db :logseq.class/Journal))
+        date-formatter (:logseq.property.journal/title-format (entity-plus/entity-memoized db :logseq.class/Journal))
         title (sanitize-title title*)
         title (sanitize-title title*)
         types (cond class?
         types (cond class?
                     #{:logseq.class/Tag}
                     #{:logseq.class/Tag}

+ 4 - 3
src/main/frontend/worker/rtc/client.cljs

@@ -326,7 +326,7 @@
 
 
 (defn new-task--push-local-ops
 (defn new-task--push-local-ops
   "Return a task: push local updates"
   "Return a task: push local updates"
-  [repo conn graph-uuid date-formatter get-ws-create-task add-log-fn]
+  [repo conn graph-uuid date-formatter get-ws-create-task *remote-profile? add-log-fn]
   (m/sp
   (m/sp
     (let [block-ops-map-coll (client-op/get&remove-all-block-ops repo)]
     (let [block-ops-map-coll (client-op/get&remove-all-block-ops repo)]
       (when-let [block-uuid->remote-ops (not-empty (gen-block-uuid->remote-ops @conn block-ops-map-coll))]
       (when-let [block-uuid->remote-ops (not-empty (gen-block-uuid->remote-ops @conn block-ops-map-coll))]
@@ -336,8 +336,9 @@
           (let [local-tx (client-op/get-local-tx repo)
           (let [local-tx (client-op/get-local-tx repo)
                 r (try
                 r (try
                     (m/? (ws-util/send&recv get-ws-create-task
                     (m/? (ws-util/send&recv get-ws-create-task
-                                            {:action "apply-ops" :graph-uuid graph-uuid
-                                             :ops ops-for-remote :t-before (or local-tx 1)}))
+                                            (cond-> {:action "apply-ops" :graph-uuid graph-uuid
+                                                     :ops ops-for-remote :t-before (or local-tx 1)}
+                                              (true? @*remote-profile?) (assoc :profile true))))
                     (catch :default e
                     (catch :default e
                       (rollback repo block-ops-map-coll)
                       (rollback repo block-ops-map-coll)
                       (throw e)))]
                       (throw e)))]

+ 6 - 1
src/main/frontend/worker/rtc/const.cljs

@@ -78,6 +78,7 @@
   "TODO: split this mix schema to multiple ones"
   "TODO: split this mix schema to multiple ones"
   [:map
   [:map
    [:req-id :string]
    [:req-id :string]
+   [:profile {:optional true} :map]
    [:t {:optional true} :int]
    [:t {:optional true} :int]
    [:t-before {:optional true} :int]
    [:t-before {:optional true} :int]
    [:failed-ops {:optional true} [:sequential to-ws-op-schema]]
    [:failed-ops {:optional true} [:sequential to-ws-op-schema]]
@@ -172,7 +173,9 @@
        (fn [api-schema]
        (fn [api-schema]
          (let [[api-name [type']] api-schema]
          (let [[api-name [type']] api-schema]
            (if (= :map type')
            (if (= :map type')
-             [api-name (vec (concat (second api-schema) [[:req-id :string] [:action :string]]))]
+             [api-name (vec (concat (second api-schema) [[:req-id :string]
+                                                         [:action :string]
+                                                         [:profile {:optional true} :boolean]]))]
              api-schema)))
              api-schema)))
        api-schema-seq)))))
        api-schema-seq)))))
 
 
@@ -190,12 +193,14 @@
         [:map
         [:map
          [:req-id :string]
          [:req-id :string]
          [:action :string]
          [:action :string]
+         [:profile {:optional true} :boolean]
          [:graph-uuid :string]
          [:graph-uuid :string]
          [:ops [:sequential to-ws-op-schema]]
          [:ops [:sequential to-ws-op-schema]]
          [:t-before :int]]
          [:t-before :int]]
         [:map
         [:map
          [:req-id :string]
          [:req-id :string]
          [:action :string]
          [:action :string]
+         [:profile {:optional true} :boolean]
          [:s3-key :string]]]]
          [:s3-key :string]]]]
       ["presign-put-temp-s3-obj"
       ["presign-put-temp-s3-obj"
        [:map]]
        [:map]]

+ 29 - 12
src/main/frontend/worker/rtc/core.cljs

@@ -180,6 +180,7 @@
    & {:keys [auto-push? debug-ws-url] :or {auto-push? true}}]
    & {:keys [auto-push? debug-ws-url] :or {auto-push? true}}]
   (let [ws-url                     (or debug-ws-url (ws-util/get-ws-url token))
   (let [ws-url                     (or debug-ws-url (ws-util/get-ws-url token))
         *auto-push?                (atom auto-push?)
         *auto-push?                (atom auto-push?)
+        *remote-profile?           (atom false)
         *last-calibrate-t          (atom nil)
         *last-calibrate-t          (atom nil)
         *online-users              (atom nil)
         *online-users              (atom nil)
         *assets-sync-loop-canceler (atom nil)
         *assets-sync-loop-canceler (atom nil)
@@ -195,10 +196,11 @@
         (r.asset/create-assets-sync-loop repo get-ws-create-task graph-uuid conn *auto-push?)
         (r.asset/create-assets-sync-loop repo get-ws-create-task graph-uuid conn *auto-push?)
         mixed-flow                 (create-mixed-flow repo get-ws-create-task *auto-push? *online-users)]
         mixed-flow                 (create-mixed-flow repo get-ws-create-task *auto-push? *online-users)]
     (assert (some? *current-ws))
     (assert (some? *current-ws))
-    {:rtc-state-flow     (create-rtc-state-flow (create-ws-state-flow *current-ws))
-     :*rtc-auto-push?    *auto-push?
-     :*online-users      *online-users
-     :onstarted-task     started-dfv
+    {:rtc-state-flow       (create-rtc-state-flow (create-ws-state-flow *current-ws))
+     :*rtc-auto-push?      *auto-push?
+     :*rtc-remote-profile? *remote-profile?
+     :*online-users        *online-users
+     :onstarted-task       started-dfv
      :rtc-loop-task
      :rtc-loop-task
      (holding-rtc-lock
      (holding-rtc-lock
       started-dfv
       started-dfv
@@ -225,7 +227,7 @@
                :local-update-check
                :local-update-check
                (m/? (r.client/new-task--push-local-ops
                (m/? (r.client/new-task--push-local-ops
                      repo conn graph-uuid date-formatter
                      repo conn graph-uuid date-formatter
-                     get-ws-create-task add-log-fn))
+                     get-ws-create-task *remote-profile? add-log-fn))
 
 
                :online-users-updated
                :online-users-updated
                (reset! *online-users (:online-users (:value event)))
                (reset! *online-users (:online-users (:value event)))
@@ -246,16 +248,21 @@
             (when @*assets-sync-loop-canceler (@*assets-sync-loop-canceler))))))}))
             (when @*assets-sync-loop-canceler (@*assets-sync-loop-canceler))))))}))
 
 
 (def ^:private empty-rtc-loop-metadata
 (def ^:private empty-rtc-loop-metadata
-  {:graph-uuid nil
+  {:repo nil
+   :graph-uuid nil
    :user-uuid nil
    :user-uuid nil
    :rtc-state-flow nil
    :rtc-state-flow nil
    :*rtc-auto-push? nil
    :*rtc-auto-push? nil
+   :*rtc-remote-profile? nil
    :*online-users nil
    :*online-users nil
    :*rtc-lock nil
    :*rtc-lock nil
    :canceler nil
    :canceler nil
    :*last-stop-exception nil})
    :*last-stop-exception nil})
 
 
-(defonce ^:private *rtc-loop-metadata (atom empty-rtc-loop-metadata))
+(defonce ^:private *rtc-loop-metadata (atom empty-rtc-loop-metadata
+                                            :validator
+                                            (fn [v] (= (set (keys empty-rtc-loop-metadata))
+                                                       (set (keys v))))))
 
 
 ;;; ================ API ================
 ;;; ================ API ================
 (defn new-task--rtc-start
 (defn new-task--rtc-start
@@ -268,7 +275,7 @@
         (let [user-uuid (:sub (worker-util/parse-jwt token))
         (let [user-uuid (:sub (worker-util/parse-jwt token))
               config (worker-state/get-config repo)
               config (worker-state/get-config repo)
               date-formatter (common-config/get-date-formatter config)
               date-formatter (common-config/get-date-formatter config)
-              {:keys [rtc-state-flow *rtc-auto-push? rtc-loop-task *online-users onstarted-task]}
+              {:keys [rtc-state-flow *rtc-auto-push? *rtc-remote-profile? rtc-loop-task *online-users onstarted-task]}
               (create-rtc-loop graph-uuid repo conn date-formatter token)
               (create-rtc-loop graph-uuid repo conn date-formatter token)
               *last-stop-exception (atom nil)
               *last-stop-exception (atom nil)
               canceler (c.m/run-task rtc-loop-task :rtc-loop-task
               canceler (c.m/run-task rtc-loop-task :rtc-loop-task
@@ -283,6 +290,7 @@
                                             :user-uuid user-uuid
                                             :user-uuid user-uuid
                                             :rtc-state-flow rtc-state-flow
                                             :rtc-state-flow rtc-state-flow
                                             :*rtc-auto-push? *rtc-auto-push?
                                             :*rtc-auto-push? *rtc-auto-push?
+                                            :*rtc-remote-profile? *rtc-remote-profile?
                                             :*online-users *online-users
                                             :*online-users *online-users
                                             :*rtc-lock *rtc-lock
                                             :*rtc-lock *rtc-lock
                                             :canceler canceler
                                             :canceler canceler
@@ -303,6 +311,11 @@
   (when-let [*auto-push? (:*rtc-auto-push? @*rtc-loop-metadata)]
   (when-let [*auto-push? (:*rtc-auto-push? @*rtc-loop-metadata)]
     (swap! *auto-push? not)))
     (swap! *auto-push? not)))
 
 
+(defn rtc-toggle-remote-profile
+  []
+  (when-let [*rtc-remote-profile? (:*rtc-remote-profile? @*rtc-loop-metadata)]
+    (swap! *rtc-remote-profile? not)))
+
 (defn new-task--get-graphs
 (defn new-task--get-graphs
   [token]
   [token]
   (let [{:keys [get-ws-create-task]} (gen-get-ws-create-map--memoized (ws-util/get-ws-url token))]
   (let [{:keys [get-ws-create-task]} (gen-get-ws-create-map--memoized (ws-util/get-ws-url token))]
@@ -356,14 +369,15 @@
   (let [rtc-loop-metadata-flow (m/watch *rtc-loop-metadata)]
   (let [rtc-loop-metadata-flow (m/watch *rtc-loop-metadata)]
     (m/ap
     (m/ap
       (let [{rtc-lock :*rtc-lock
       (let [{rtc-lock :*rtc-lock
-             :keys [repo graph-uuid user-uuid rtc-state-flow *rtc-auto-push? *online-users
-                    *last-stop-exception]}
+             :keys [repo graph-uuid user-uuid rtc-state-flow *rtc-auto-push? *rtc-remote-profile?
+                    *online-users *last-stop-exception]}
             (m/?< rtc-loop-metadata-flow)]
             (m/?< rtc-loop-metadata-flow)]
         (try
         (try
           (when (and repo rtc-state-flow *rtc-auto-push? rtc-lock)
           (when (and repo rtc-state-flow *rtc-auto-push? rtc-lock)
             (m/?<
             (m/?<
              (m/latest
              (m/latest
-              (fn [rtc-state rtc-auto-push? rtc-lock online-users pending-local-ops-count local-tx remote-tx]
+              (fn [rtc-state rtc-auto-push? rtc-remote-profile?
+                   rtc-lock online-users pending-local-ops-count local-tx remote-tx]
                 {:graph-uuid graph-uuid
                 {:graph-uuid graph-uuid
                  :user-uuid user-uuid
                  :user-uuid user-uuid
                  :unpushed-block-update-count pending-local-ops-count
                  :unpushed-block-update-count pending-local-ops-count
@@ -372,9 +386,12 @@
                  :rtc-state rtc-state
                  :rtc-state rtc-state
                  :rtc-lock rtc-lock
                  :rtc-lock rtc-lock
                  :auto-push? rtc-auto-push?
                  :auto-push? rtc-auto-push?
+                 :remote-profile? rtc-remote-profile?
                  :online-users online-users
                  :online-users online-users
                  :last-stop-exception-ex-data (some-> *last-stop-exception deref ex-data)})
                  :last-stop-exception-ex-data (some-> *last-stop-exception deref ex-data)})
-              rtc-state-flow (m/watch *rtc-auto-push?) (m/watch rtc-lock) (m/watch *online-users)
+              rtc-state-flow
+              (m/watch *rtc-auto-push?) (m/watch *rtc-remote-profile?)
+              (m/watch rtc-lock) (m/watch *online-users)
               (client-op/create-pending-block-ops-count-flow repo)
               (client-op/create-pending-block-ops-count-flow repo)
               (rtc-log-and-state/create-local-t-flow graph-uuid)
               (rtc-log-and-state/create-local-t-flow graph-uuid)
               (rtc-log-and-state/create-remote-t-flow graph-uuid))))
               (rtc-log-and-state/create-remote-t-flow graph-uuid))))