wip: impl datascript storage based on sqlite-opfs

This commit is contained in:
Andelf
2023-11-30 02:04:55 +08:00
parent 86aa39e893
commit ca24545b53
2 changed files with 87 additions and 23 deletions

View File

@@ -3,10 +3,54 @@
(:require ["@logseq/sqlite" :as sqlite-db :default wasm-bindgen-init]
["comlink" :as Comlink]
[promesa.core :as p]
[shadow.cljs.modern :refer [defclass]]))
[datascript.storage :refer [IStorage]]
[cljs.cache :as cache]
[cljs.reader :as reader]
[datascript.core :as d]
[logseq.db.frontend.schema :as db-schema]
[shadow.cljs.modern :refer [defclass]]
[datascript.transit :as dt]
[clojure.edn :as edn]))
(def *wasm-loaded (atom false))
;; datascript conns
(defonce conns (atom nil))
(defn get-conn
[repo]
(get @conns repo))
(defn upsert-addr-content!
"Upsert addr+data-seq"
[repo data]
(.upsert_addr_content sqlite-db repo data))
(defn restore-data-from-addr
[repo addr]
(.get_content_by_addr sqlite-db repo addr))
(defn new-sqlite-storage
[repo {:keys [threshold]
:or {threshold 4096}}]
(let [_cache (cache/lru-cache-factory {} :threshold threshold)]
(reify IStorage
(-store [_ addr+data-seq]
(let [data (->>
(map
(fn [[addr data]]
#js {:addr addr
:content (pr-str data)})
addr+data-seq)
(to-array))]
(upsert-addr-content! repo data)
{:result "ok"}))
(-restore [_ addr]
(let [content (restore-data-from-addr repo addr)]
(edn/read-string content))))))
#_:clj-kondo/ignore
(defclass SQLiteDB
(extends js/Object)
@@ -51,7 +95,33 @@
(p/do!
(.ensure_init sqlite-db)
(.init_db sqlite-db repo) ;; close another and init this one
(.new_db sqlite-db repo)))
(.new_db sqlite-db repo)
(let [db-name repo
storage (new-sqlite-storage db-name {})
conn (or (d/restore-conn storage)
(d/create-conn db-schema/schema-for-db-based-graph {:storage storage}))]
(swap! conns assoc db-name conn)
nil)))
(transact
[_this repo tx-data tx-meta]
(when-let [conn (get-conn repo)]
(try
(let [tx-data (reader/read-string tx-data)
tx-meta (reader/read-string tx-meta)]
(d/transact! conn tx-data tx-meta))
(catch :default e
(prn :debug :error)
(js/console.error e)))))
(getInitialData
[_this repo]
(when-let [conn (get-conn repo)]
(let [db @conn]
(->> (d/datoms db :eavt)
;; (remove (fn [e] (= :block/content (:a e))))
vec
dt/write-transit-str))))
(openDB
[_this repo]

View File

@@ -112,7 +112,7 @@
(p/catch (fn [error]
(if (string/includes? (str error) "NoModificationAllowedError")
(notification/show! [:div (str "Avoid opening the same graph in multi-tabs. Error: " error)] :error)
(notification/show! [:div (str "SQLiteDB backend error: " error)] :error))
(notification/show! [:div (str "SQLiteDB creation error: " error)] :error))
nil))))
@@ -127,34 +127,28 @@
(p/let [^js sqlite (ensure-sqlite-init)]
(.unsafeUnlinkDB sqlite repo)))
(<transact-data [_this repo upsert-blocks deleted-uuids]
(p->c (p/let [^js sqlite (ensure-sqlite-init)
deleted (clj->js (map str deleted-uuids))
_ (when (seq deleted)
(.deleteBlocks sqlite repo deleted))
upsert-blocks (clj->js (map ds->sqlite-block upsert-blocks))]
(.upsertBlocks sqlite repo upsert-blocks))))
(<transact-data [_this repo tx-data tx-meta]
(prn ::transact-data repo (count tx-data) (count tx-meta))
(p->c
(p/let [^js sqlite (ensure-sqlite-init)
_ (.transact sqlite repo (pr-str tx-data) (pr-str tx-meta))]
nil)))
(<fetch-initital-data [_this repo _opts]
(prn ::fetch-initital-data repo)
(-> (p/let [^js sqlite (ensure-sqlite-init)
;; <fetch-initital-data is called when init/re-loading graph
;; the underlying DB should be opened
_ (.openDB sqlite repo)
all-pages (.fetchAllPages sqlite repo)
all-blocks (.fetchAllBlocks sqlite repo)
journal-blocks (.fetchRecentJournals sqlite repo)
init-data (.fetchInitData sqlite repo)]
#js {:all-blocks all-blocks
:all-pages all-pages
:journal-blocks journal-blocks
:init-data init-data})
;; <fetch-initital-data is called when init/re-loading graph
;; the underlying DB should be opened
_ (.openDB sqlite repo)]
(.getInitialData sqlite repo))
(p/catch (fn [error]
(prn ::fuck-error)
(if (string/includes? (str error) "NoModificationAllowedError")
(notification/show! [:div (str "Avoid opening the same graph in multi-tabs. Error: " error)] :error)
(notification/show! [:div (str "SQLiteDB backend error: " error)] :error))
(notification/show! [:div (str "SQLiteDB fetch error: " error)] :error))
{}))))
(<fetch-blocks-excluding [_this repo exclude-uuids _opts]
(p/let [^js sqlite (ensure-sqlite-init)]
(.fetchBlocksExcluding sqlite repo (clj->js exclude-uuids)))))