Browse Source

enhance: check missing addresses on dev

Tienson Qin 8 months ago
parent
commit
767f86344b
2 changed files with 44 additions and 28 deletions
  1. 41 28
      src/main/frontend/worker/db_worker.cljs
  2. 3 0
      src/main/frontend/worker/util.cljc

+ 41 - 28
src/main/frontend/worker/db_worker.cljs

@@ -158,42 +158,54 @@
                                             :bind #js [addr]}))))))))
                                             :bind #js [addr]}))))))))
 
 
 (defn- find-missing-addresses
 (defn- find-missing-addresses
-  [^Object db]
-  (let [schema (some->> (.exec db #js {:sql "select content from kvs where addr = 0"
-                                       :rowMode "array"})
-                        bean/->clj
-                        ffirst
-                        sqlite-util/transit-read)
-        result (->> (.exec db #js {:sql "select addr, addresses from kvs"
-                                   :rowMode "array"})
-                    bean/->clj
-                    (map (fn [[addr addresses]]
-                           [addr (bean/->clj (js/JSON.parse addresses))])))
-        used-addresses (set (concat (mapcat second result)
-                                    [0 1 (:eavt schema) (:avet schema) (:aevt schema)]))
-        missing-addresses (clojure.set/difference used-addresses (set (map first result)))]
-    (when (seq missing-addresses)
-      (worker-util/post-message :capture-error
-                                {:error "db-missing-addresses"
-                                 :payload {:missing-addresses missing-addresses}})
-      (prn :error :missing-addresses missing-addresses))
-    missing-addresses))
+  [^Object db & {:keys [delete-addrs]}]
+  (worker-util/profile
+   "find-missing-addresses"
+   (let [schema (some->> (.exec db #js {:sql "select content from kvs where addr = 0"
+                                        :rowMode "array"})
+                         bean/->clj
+                         ffirst
+                         sqlite-util/transit-read)
+         result (->> (.exec db #js {:sql "select addr, addresses from kvs"
+                                    :rowMode "array"})
+                     bean/->clj
+                     (keep (fn [[addr addresses]]
+                             (when-not (and delete-addrs (delete-addrs addr))
+                               [addr (bean/->clj (js/JSON.parse addresses))]))))
+         used-addresses (-> (set (concat (mapcat second result)
+                                         [0 1 (:eavt schema) (:avet schema) (:aevt schema)]))
+                            (clojure.set/difference delete-addrs))
+         missing-addresses (clojure.set/difference used-addresses (set (map first result)))]
+     (when (seq missing-addresses)
+       (prn :error :missing-addresses missing-addresses)
+       (if worker-util/dev?
+         (throw (ex-info "Found missing addresses that shouldn't happen" {:missing-addresses missing-addresses}))
+         (worker-util/post-message :capture-error
+                                   {:error "db-missing-addresses"
+                                    :payload {:missing-addresses missing-addresses}})))
+     missing-addresses)))
 
 
 (defn upsert-addr-content!
 (defn upsert-addr-content!
   "Upsert addr+data-seq. Update sqlite-cli/upsert-addr-content! when making changes"
   "Upsert addr+data-seq. Update sqlite-cli/upsert-addr-content! when making changes"
-  [repo data delete-addrs & {:keys [client-ops-db?] :or {client-ops-db? false}}]
-  (let [^Object db (worker-state/get-sqlite-conn repo (if client-ops-db? :client-ops :db))]
+  [repo data delete-addrs* & {:keys [client-ops-db?] :or {client-ops-db? false}}]
+  (let [^Object db (worker-state/get-sqlite-conn repo (if client-ops-db? :client-ops :db))
+        delete-addrs (set delete-addrs*)]
     (assert (some? db) "sqlite db not exists")
     (assert (some? db) "sqlite db not exists")
     (.transaction db (fn [tx]
     (.transaction db (fn [tx]
                        (doseq [item data]
                        (doseq [item data]
                          (.exec tx #js {:sql "INSERT INTO kvs (addr, content, addresses) values ($addr, $content, $addresses) on conflict(addr) do update set content = $content, addresses = $addresses"
                          (.exec tx #js {:sql "INSERT INTO kvs (addr, content, addresses) values ($addr, $content, $addresses) on conflict(addr) do update set content = $content, addresses = $addresses"
                                         :bind item}))))
                                         :bind item}))))
     (when (seq delete-addrs)
     (when (seq delete-addrs)
-      (.transaction db (fn [tx]
-                         ;; (prn :debug :delete-addrs delete-addrs)
-                         (doseq [addr delete-addrs]
-                           (.exec tx #js {:sql "Delete from kvs WHERE addr = ? AND NOT EXISTS (SELECT 1 FROM json_each(addresses) WHERE value = ?);"
-                                          :bind #js [addr]})))))))
+      (let [missing-addrs (when worker-util/dev?
+                            (seq (find-missing-addresses db {:delete-addrs delete-addrs})))
+            delete-addrs' (if missing-addrs
+                            (remove (set missing-addrs) delete-addrs)
+                            delete-addrs)]
+        (when (seq delete-addrs')
+          (.transaction db (fn [tx]
+                             (doseq [addr delete-addrs']
+                               (.exec tx #js {:sql "Delete from kvs WHERE addr = ? AND NOT EXISTS (SELECT 1 FROM json_each(addresses) WHERE value = ?);"
+                                              :bind #js [addr]})))))))))
 
 
 (defn restore-data-from-addr
 (defn restore-data-from-addr
   "Update sqlite-cli/restore-data-from-addr when making changes"
   "Update sqlite-cli/restore-data-from-addr when making changes"
@@ -366,8 +378,9 @@
 
 
           (db-migrate/migrate conn search-db)
           (db-migrate/migrate conn search-db)
 
 
+          ;; TODO: Remove this once we can ensure there's no bug for missing addresses
           (catch :default e
           (catch :default e
-            (log/error "DB migrate failed, error: " e)
+            (log/error (str "DB migrate failed for " repo ", error:") e)
             (if (= (.-message e) "DB missing addresses")
             (if (= (.-message e) "DB missing addresses")
               (do
               (do
                 (rebuild-db-from-datoms! conn db import-type)
                 (rebuild-db-from-datoms! conn db import-type)

+ 3 - 0
src/main/frontend/worker/util.cljc

@@ -21,6 +21,9 @@
             res#))
             res#))
         (do ~@body))))
         (do ~@body))))
 
 
+#?(:cljs
+   (def dev? js/goog.DEBUG))
+
 #?(:cljs
 #?(:cljs
    (do
    (do
      (def post-message wfu/post-message)
      (def post-message wfu/post-message)