Pārlūkot izejas kodu

perf(rtc): reduce transact calls in rtc-add-ops

rcmerci 11 mēneši atpakaļ
vecāks
revīzija
593c1fe19b
1 mainītis faili ar 66 papildinājumiem un 50 dzēšanām
  1. 66 50
      src/main/frontend/worker/rtc/client_op.cljs

+ 66 - 50
src/main/frontend/worker/rtc/client_op.cljs

@@ -120,60 +120,76 @@
          {:block-uuid block-uuid
           :av-coll (concat av-coll1 av-coll2)}]))))
 
-(defn add-ops*
-  [conn ops]
-  (let [ops (ops-coercer ops)]
-    (letfn [(already-removed? [remove-op t]
-              (some-> remove-op second (> t)))
-            (add-after-remove? [move-op t]
-              (some-> move-op second (> t)))]
-      (doseq [op ops]
-        (let [[op-type t value] op
-              {:keys [block-uuid]} value
-              exist-block-ops-entity (d/entity @conn [:block/uuid block-uuid])
-              e (:db/id exist-block-ops-entity)
-              tx-data
-              (case op-type
-                :move
-                (let [remove-op (get exist-block-ops-entity :remove)]
-                  (when-not (already-removed? remove-op t)
-                    (cond-> [{:block/uuid block-uuid
-                              :move op}]
-                      remove-op (conj [:db.fn/retractAttribute e :remove]))))
-                :update
-                (let [remove-op (get exist-block-ops-entity :remove)]
-                  (when-not (already-removed? remove-op t)
-                    (let [origin-update-op (get exist-block-ops-entity :update)
-                          op* (if origin-update-op (merge-update-ops origin-update-op op) op)]
-                      (cond-> [{:block/uuid block-uuid
-                                :update op*}]
-                        remove-op (conj [:db.fn/retractAttribute e :remove])))))
-                :remove
-                (let [move-op (get exist-block-ops-entity :move)]
-                  (when-not (add-after-remove? move-op t)
-                    (cond-> [{:block/uuid block-uuid
-                              :remove op}]
-                      move-op (conj [:db.fn/retractAttribute e :move]))))
-                :update-page
-                (let [remove-page-op (get exist-block-ops-entity :remove-page)]
-                  (when-not (already-removed? remove-page-op t)
-                    (cond-> [{:block/uuid block-uuid
-                              :update-page op}]
-                      remove-page-op (conj [:db.fn/retractAttribute e :remove-page]))))
-                :remove-page
-                (let [update-page-op (get exist-block-ops-entity :update-page)]
-                  (when-not (add-after-remove? update-page-op t)
-                    (cond-> [{:block/uuid block-uuid
-                              :remove-page op}]
-                      update-page-op (conj [:db.fn/retractAttribute e :update-page])))))]
-          (when (seq tx-data)
-            (d/transact! conn tx-data)))))))
+(defn- generate-block-ops-tx-data
+  [client-ops-db ops]
+  (let [sorted-ops (sort-by second ops)
+        block-uuids (map (fn [[_op-type _t value]] (:block-uuid value)) sorted-ops)
+        ents (d/pull-many client-ops-db '[*] (map (fn [block-uuid] [:block/uuid block-uuid]) block-uuids))
+        op-types [:move :update :remove :update-page :remove-page]
+        init-block-uuid->op-type->op
+        (into {}
+              (map (fn [ent]
+                     [(:block/uuid ent)
+                      (into {}
+                            (keep
+                             (fn [op-type]
+                               (when-let [op (get ent op-type)]
+                                 [op-type op])))
+                            op-types)]))
+              ents)
+        block-uuid->op-type->op
+        (reduce
+         (fn [r op]
+           (let [[op-type _t value] op
+                 block-uuid (:block-uuid value)]
+             (case op-type
+               :move
+               (-> r
+                   (update block-uuid assoc :remove :retract)
+                   (assoc-in [block-uuid :move] op))
+               :update
+               (-> r
+                   (update block-uuid assoc :remove :retract)
+                   (update-in [block-uuid :update] (fn [old-op]
+                                                     (if old-op
+                                                       (merge-update-ops old-op op)
+                                                       op))))
+               :remove
+               (-> r
+                   (update block-uuid assoc :move :retract :update :retract)
+                   (assoc-in [block-uuid :remove] op))
+               :update-page
+               (-> r
+                   (update block-uuid assoc :remove-page :retract)
+                   (assoc-in [block-uuid :update-page] op))
+               :remove-page
+               (-> r
+                   (update block-uuid assoc :update-page :retract)
+                   (assoc-in [block-uuid :remove-page] op)))))
+         init-block-uuid->op-type->op sorted-ops)]
+    (mapcat
+     (fn [[block-uuid op-type->op]]
+       (let [tmpid (str block-uuid)]
+         (when-let [tx-data
+                    (not-empty
+                     (keep
+                      (fn [[op-type op]]
+                        (cond
+                          (= :retract op)
+                          [:db.fn/retractAttribute [:block/uuid block-uuid] op-type]
+                          (some? op)
+                          [:db/add tmpid op-type op]))
+                      op-type->op))]
+           (cons [:db/add tmpid :block/uuid block-uuid] tx-data))))
+     block-uuid->op-type->op)))
 
 (defn add-ops
   [repo ops]
-  (let [conn (worker-state/get-client-ops-conn repo)]
+  (let [conn (worker-state/get-client-ops-conn repo)
+        ops (ops-coercer ops)]
     (assert (some? conn) repo)
-    (add-ops* conn ops)))
+    (when-let [tx-data (not-empty (generate-block-ops-tx-data @conn ops))]
+      (d/transact! conn tx-data))))
 
 (defn- get-all-block-ops*
   "Return e->op-map"