Browse Source

add validate-struct for debug

rcmerci 4 years ago
parent
commit
cdeac06c24
1 changed files with 83 additions and 45 deletions
  1. 83 45
      src/main/frontend/modules/outliner/yjs.cljs

+ 83 - 45
src/main/frontend/modules/outliner/yjs.cljs

@@ -14,6 +14,9 @@
             [datascript.core :as d]))
 (set! *warn-on-infer* false)
 
+(def ^:dynamic *debug* true)
+(declare validate-struct)
+
 (def doc-local (y/Doc.))
 (def doc-remote (y/Doc.))
 
@@ -368,26 +371,35 @@ return [2 3]
 
 (defn- observe-struct-fn [page-name]
   (fn [events]
-    (def xxx events)
-    (let [[arrays added-items deleted-items] (events->array&items events)
-          contentmap (contentmap)]
-      (mapv
-       (fn [item]
-         (observe-struct-fn-aux-insert-ids (.-arr (.-content item)) page-name contentmap)
-         (when-some [yarray (.-type (.-content item))]
-           (observe-struct-fn-aux-insert-items-array yarray page-name contentmap)))
-       added-items))))
+    (try
+      (let [[arrays added-items deleted-items] (events->array&items events)
+            contentmap (contentmap)]
+        (mapv
+         (fn [item]
+           (observe-struct-fn-aux-insert-ids (.-arr (.-content item)) page-name contentmap)
+           (when-some [yarray (.-type (.-content item))]
+             (observe-struct-fn-aux-insert-items-array yarray page-name contentmap)))
+         added-items))
+      (catch js/Error e
+        (js/console.log "observe-struct-fn:")
+        (js/console.log events)
+        (js/console.log e)))))
 
 (def observe-struct-fn-memo (memoize observe-struct-fn))
 
 (defn- observe-content-fn [event]
-  (when-not (.-local (.-transaction event))
-    (let [keys (js->clj (into [] (.-keys event)))]
-      (mapv (fn [[k v]]
-              (case (get v "action")
-                "update" (update-block-content k)
-                "delete" (delete-node k)
-                (println "action" v))) keys))))
+  (try
+    (when-not (.-local (.-transaction event))
+      (let [keys (js->clj (into [] (.-keys event)))]
+        (mapv (fn [[k v]]
+                (case (get v "action")
+                  "update" (update-block-content k)
+                  "delete" (delete-node k)
+                  (println "action" v))) keys)))
+    (catch js/Error e
+      (js/console.log "observe-content-fn:")
+      (js/console.log event)
+      (js/console.log e))))
 
 (defn observe-page-doc [page-name doc]
   (let [struct (.getArray doc (str page-name "-struct"))
@@ -484,6 +496,7 @@ return [2 3]
 
 (defn start-sync-page [page-name]
   (let [page-blocks (db/get-page-blocks-no-cache page-name)]
+    (unobserve-page-doc page-name doc-local)
     (page-blocks->doc page-blocks page-name)
     (sync-doc doc-local doc-remote)
     (distinct-struct (structarray page-name) (atom #{}))
@@ -591,6 +604,7 @@ return [2 3]
         (insert-nodes-yjs struct new-nodes-tree (str (:block/uuid target-block)) sibling?)
         (distinct-struct struct (atom #{}))
         (merge-doc doc-remote doc-local)
+        (when *debug* (validate-struct struct))
         (outliner-core/insert-nodes new-nodes-tree target-node sibling?)))))
 
 (defn insert-node-yjs [struct new-node target-uuid sibling?]
@@ -611,6 +625,7 @@ return [2 3]
          (insert-node-yjs struct new-node (str (:block/uuid target-block)) sibling?)
          (distinct-struct struct (atom #{}))
          (merge-doc doc-remote doc-local)
+         (when *debug* (validate-struct struct))
          (outliner-core/insert-node new-node target-node sibling? opts))))))
 
 
@@ -664,9 +679,8 @@ return [2 3]
           (delete-range-nodes-suffix-part same-prefix-vec pos-vec2*-after-delete-prefix-part struct))
         (delete-range-nodes-suffix-part same-prefix-vec pos-vec2* struct)))))
 
-(defn delete-nodes-yjs [page-name start-uuid end-uuid block-ids]
-  (let [struct (structarray page-name)
-        start-pos (find-pos struct (str start-uuid))
+(defn delete-nodes-yjs [struct start-uuid end-uuid block-ids]
+  (let [start-pos (find-pos struct (str start-uuid))
         end-pos (find-pos struct (str end-uuid))
         ids (mapv (fn [id-tuple] (str (second id-tuple))) block-ids)]
     (delete-range-nodes start-pos end-pos struct)
@@ -681,23 +695,26 @@ return [2 3]
                               (:block/name (db/entity (:db/id (:block/page start-block)))))]
       (when-some [start-uuid (:block/uuid start-block)]
         (when-some [end-uuid (:block/uuid end-block)]
-          (delete-nodes-yjs page-name start-uuid end-uuid block-ids)
-          (distinct-struct (structarray page-name) (atom #{}))
-          (merge-doc doc-remote doc-local)
-          (outliner-core/delete-nodes start-node end-node block-ids))))))
-
-(defn delete-node-yjs [page-name id]
-  (let [struct (structarray page-name)
-        pos (find-pos struct id)]
+          (let [struct (structarray page-name)]
+            (delete-nodes-yjs struct start-uuid end-uuid block-ids)
+            (distinct-struct struct (atom #{}))
+            (merge-doc doc-remote doc-local)
+            (when *debug* (validate-struct struct))
+            (outliner-core/delete-nodes start-node end-node block-ids)))))))
+
+(defn delete-node-yjs [struct id]
+  (let [pos (find-pos struct id)]
     (delete-item pos struct)
     (dissoc-contents [id] (contentmap))))
 
 (defn delete-node-op [node children?]
   (let [block (:data node)]
     (when-some [page-name (:block/name (db/entity (:db/id (:block/page block))))]
-      (let [uuid (str (:block/uuid block))]
-        (delete-node-yjs page-name uuid)
+      (let [uuid (str (:block/uuid block))
+            struct (structarray page-name)]
+        (delete-node-yjs struct uuid)
         (merge-doc doc-remote doc-local)
+        (when *debug* (validate-struct struct))
         (outliner-core/delete-node node children?)))))
 
 (defn save-node-op [node]
@@ -705,10 +722,12 @@ return [2 3]
         contentmap (contentmap)]
     (when-some [page-name (:block/name (db/entity (:db/id (:block/page block))))]
       (when-some [block-uuid (:block/uuid block)]
-        (.set contentmap (str block-uuid) (:block/content block))
-        (distinct-struct (structarray page-name) (atom #{}))
-        (merge-doc doc-remote doc-local)
-        (outliner-core/save-node node)))))
+        (let [struct (structarray page-name)]
+          (.set contentmap (str block-uuid) (:block/content block))
+          (distinct-struct struct (atom #{}))
+          (merge-doc doc-remote doc-local)
+          (when *debug* (validate-struct struct))
+          (outliner-core/save-node node))))))
 
 (defn- outdentable? [pos]
   (> (count pos) 1))
@@ -763,22 +782,23 @@ return [2 3]
             (.insert item-parent-parent-array (+ insert-pos (if item-children-clone 2 1))
                      (clj->js [item-parent-array-clone]))))))))
 
-(defn- indent-outdent-nodes-yjs [page-name ids indent?]
-  (let [struct (structarray page-name)]
-    (mapv
-     (fn [id]
-       (if indent?
-         (indent-item struct id)
-         (outdent-item struct id)))
-     ids)))
+(defn- indent-outdent-nodes-yjs [struct ids indent?]
+  (mapv
+   (fn [id]
+     (if indent?
+       (indent-item struct id)
+       (outdent-item struct id)))
+   ids))
 
 (defn indent-outdent-nodes-op [nodes indent?]
   (when-some [page-name
               (:block/name (db/entity (:db/id (:block/page (:data (first nodes))))))]
-    (let [ids (mapv (fn [node] (str (:block/uuid (:data node)))) nodes)]
+    (let [ids (mapv (fn [node] (str (:block/uuid (:data node)))) nodes)
+          struct (structarray page-name)]
       (println "[YJS] indent-outdent-nodes(before):" nodes indent?)
-      (indent-outdent-nodes-yjs page-name ids indent?)
+      (indent-outdent-nodes-yjs struct ids indent?)
       (merge-doc doc-remote doc-local)
+      (when *debug* (validate-struct struct))
       (outliner-core/indent-outdent-nodes nodes indent?)
       (println "[YJS] indent-outdent-nodes(after):"
                (mapv (fn [node]
@@ -822,6 +842,7 @@ return [2 3]
           target-id (str (:block/uuid (:data target-node)))]
       (move-subtree-same-page-yjs struct root-id target-id sibling?)
       (merge-doc doc-remote doc-local)
+      (when *debug* (validate-struct struct))
       (outliner-core/move-subtree root target-node sibling?))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -862,5 +883,22 @@ return [2 3]
   (.insert (.get test-struct 2) 2 (clj->js [(y/Array.)]))
   (.insert (.get (.get test-struct 2) 2) 0 (clj->js ["5"]))
   (.observeDeep test-struct (fn [e] (def eee e)))
-  (println (.toJSON test-struct))
- )
+  (println (.toJSON test-struct)))
+
+
+
+(defn- validate-struct-aux [arr parent-pos]
+  (loop [i 0]
+    (when (< i (count arr))
+      (when (vector? (arr i))
+        (assert (not= 0 i)
+                (str "vector at pos 0, pos: " (conj parent-pos i)))
+        (assert (and (> i 0) (vector? (arr (dec i))))
+                (str "continuous arrays, pos: " (conj parent-pos i)))
+        (validate-struct-aux (arr i) (conj parent-pos i)))
+      (recur (inc i)))))
+
+(defn- validate-struct [struct]
+  "ensure struct array has a legal structure"
+  (let [arr (js->clj (.toJSON struct))]
+    (validate-struct-aux arr [])))