mirror of
https://github.com/logseq/logseq.git
synced 2026-05-27 14:14:24 +00:00
wip: impl datascript storage based on sqlite-opfs
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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)))))
|
||||
|
||||
Reference in New Issue
Block a user