mirror of
https://github.com/logseq/logseq.git
synced 2026-04-24 22:25:01 +00:00
refactor(rtc): remove op-mem-layer
This commit is contained in:
@@ -88,3 +88,5 @@ frontend.worker.rtc.asset-sync/<loop-for-assets-sync
|
||||
frontend.worker.rtc.hash/hash-blocks
|
||||
;; Repl fn
|
||||
frontend.rum/use-atom-in
|
||||
;; missionary utils
|
||||
frontend.common.missionary-util/<!
|
||||
@@ -191,10 +191,11 @@
|
||||
:client-ops client-ops-db})
|
||||
(.exec db "PRAGMA locking_mode=exclusive")
|
||||
(sqlite-common-db/create-kvs-table! db)
|
||||
(sqlite-common-db/create-kvs-table! client-ops-db)
|
||||
(search/create-tables-and-triggers! search-db)
|
||||
(let [schema (sqlite-util/get-schema repo)
|
||||
conn (sqlite-common-db/get-storage-conn storage schema)
|
||||
client-ops-conn (sqlite-common-db/get-storage-conn storage client-op/schema-in-db)
|
||||
client-ops-conn (sqlite-common-db/get-storage-conn client-ops-storage client-op/schema-in-db)
|
||||
initial-data-exists? (d/entity @conn :logseq.class/Root)]
|
||||
(swap! *datascript-conns assoc repo conn)
|
||||
(swap! *client-ops-conns assoc repo client-ops-conn)
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
(ns frontend.worker.rtc.op-idb-layer
|
||||
"Fns to read/write client-ops from/into indexeddb."
|
||||
(:require ["/frontend/idbkv" :as idb-keyval]
|
||||
[promesa.core :as p]
|
||||
[logseq.db.sqlite.util :as sqlite-util]
|
||||
[logseq.db :as ldb]))
|
||||
|
||||
(def stores (atom {}))
|
||||
|
||||
(defn- ensure-store
|
||||
"Return nil when 'repo' is not a db-graph"
|
||||
[repo]
|
||||
{:pre [(some? repo)]}
|
||||
(when (sqlite-util/db-based-graph? repo)
|
||||
(if-let [s (@stores repo)]
|
||||
s
|
||||
(do (swap! stores assoc repo (idb-keyval/newStore (str "rtc-ops-" repo) "ops"))
|
||||
(@stores repo)))))
|
||||
|
||||
(defn <reset2!
|
||||
[repo v]
|
||||
(p/do!
|
||||
(when-let [store (ensure-store repo)]
|
||||
(let [v (ldb/write-transit-str v)]
|
||||
(idb-keyval/set "v" v store)))))
|
||||
|
||||
(defn <read2
|
||||
[repo]
|
||||
(p/do!
|
||||
(when-let [store (ensure-store repo)]
|
||||
(p/let [v (idb-keyval/get "v" store)]
|
||||
(when v
|
||||
(ldb/read-transit-str v))))))
|
||||
@@ -1,402 +0,0 @@
|
||||
(ns frontend.worker.rtc.op-mem-layer
|
||||
"Store client-ops in memory.
|
||||
And sync these ops to indexedDb automatically."
|
||||
(:require [clojure.set :as set]
|
||||
[frontend.common.missionary-util :as c.m]
|
||||
[frontend.worker.rtc.const :as rtc-const]
|
||||
[frontend.worker.rtc.op-idb-layer :as op-idb-layer]
|
||||
[frontend.worker.state :as worker-state]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.db.sqlite.util :as sqlite-util]
|
||||
[malli.core :as ma]
|
||||
[malli.transform :as mt]
|
||||
[missionary.core :as m]
|
||||
[promesa.core :as p])
|
||||
(:import [missionary Cancelled]))
|
||||
|
||||
(def op-schema
|
||||
[:multi {:dispatch first}
|
||||
[:move
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:block-uuid :uuid]]]]]
|
||||
[:remove
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:block-uuid :uuid]]]]]
|
||||
[:update-page
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:block-uuid :uuid]]]]]
|
||||
[:remove-page
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:block-uuid :uuid]]]]]
|
||||
[:update
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:block-uuid :uuid]
|
||||
[:av-coll [:sequential rtc-const/av-schema]]]]]]
|
||||
|
||||
[:update-asset
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:asset-uuid :uuid]]]]]
|
||||
[:remove-asset
|
||||
[:catn
|
||||
[:op :keyword]
|
||||
[:t :int]
|
||||
[:value [:map
|
||||
[:asset-uuid :uuid]]]]]])
|
||||
|
||||
(def ops-schema [:sequential op-schema])
|
||||
|
||||
(def ops-coercer (ma/coercer ops-schema mt/json-transformer nil
|
||||
#(do (prn ::bad-ops (:value %))
|
||||
(ma/-fail! ::ops-schema %))))
|
||||
|
||||
(def ops-store-value-schema
|
||||
[:map
|
||||
[:graph-uuid {:optional true} :string]
|
||||
[:local-tx {:optional true} :int]
|
||||
[:block-uuid->ops [:map-of :uuid
|
||||
[:map-of [:enum :move :remove :update :update-page :remove-page] :any]]]
|
||||
;; TODO: remove :asset-uuid->ops
|
||||
[:asset-uuid->ops [:map-of :uuid
|
||||
[:map-of [:enum :update-asset :remove-asset] :any]]]
|
||||
[:t+block-uuid-sorted-set [:set [:cat :int :uuid]]]])
|
||||
|
||||
(def ops-store-schema
|
||||
[:map-of :string ; repo-name
|
||||
[:map
|
||||
[:current-branch ops-store-value-schema]
|
||||
[:old-branch {:optional true} [:maybe ops-store-value-schema]]]])
|
||||
|
||||
(def ops-store-schema-coercer (ma/coercer ops-store-schema nil nil #(ma/-fail! ::ops-store-schema %)))
|
||||
|
||||
(defonce *ops-store (atom {} :validator ops-store-schema-coercer))
|
||||
|
||||
(defn- merge-update-ops
|
||||
[update-op1 update-op2]
|
||||
{:pre [(= :update (first update-op1))
|
||||
(= :update (first update-op2))
|
||||
(= (:block-uuid (last update-op1))
|
||||
(:block-uuid (last update-op2)))]}
|
||||
(let [t1 (second update-op1)
|
||||
t2 (second update-op2)]
|
||||
(if (> t1 t2)
|
||||
(merge-update-ops update-op2 update-op1)
|
||||
(let [{av-coll1 :av-coll block-uuid :block-uuid} (last update-op1)
|
||||
av-coll2 (:av-coll (last update-op2))]
|
||||
[:update t2
|
||||
{:block-uuid block-uuid
|
||||
:av-coll (concat av-coll1 av-coll2)}]))))
|
||||
|
||||
(defn- block-uuid->min-t
|
||||
[block-uuid->ops block-uuid]
|
||||
(some->> (block-uuid->ops block-uuid)
|
||||
vals
|
||||
(map second)
|
||||
seq
|
||||
(apply min)))
|
||||
|
||||
(defn- update-t+block-uuid-sorted-set
|
||||
[t+block-uuid-sorted-set old-block-uuid->ops block-uuid->ops block-uuid]
|
||||
(let [origin-min-t (block-uuid->min-t old-block-uuid->ops block-uuid)
|
||||
min-t (block-uuid->min-t block-uuid->ops block-uuid)]
|
||||
(cond-> t+block-uuid-sorted-set
|
||||
origin-min-t (disj [origin-min-t block-uuid])
|
||||
true (conj [min-t block-uuid]))))
|
||||
|
||||
(defn ^:large-vars/cleanup-todo add-ops-aux
|
||||
[ops block-uuid->ops t+block-uuid-sorted-set]
|
||||
(loop [block-uuid->ops block-uuid->ops
|
||||
t+block-uuid-sorted-set t+block-uuid-sorted-set
|
||||
[op & others] ops]
|
||||
(if-not op
|
||||
{:block-uuid->ops block-uuid->ops
|
||||
:t+block-uuid-sorted-set t+block-uuid-sorted-set}
|
||||
(let [[op-type t value] op
|
||||
{:keys [block-uuid]} value
|
||||
exist-ops (some-> block-uuid block-uuid->ops)]
|
||||
(case op-type
|
||||
:move
|
||||
(let [already-removed? (some-> (get exist-ops :remove) second (> t))]
|
||||
(if already-removed?
|
||||
(recur block-uuid->ops t+block-uuid-sorted-set others)
|
||||
(let [block-uuid->ops* (-> block-uuid->ops
|
||||
(assoc-in [block-uuid :move] op)
|
||||
(update block-uuid dissoc :remove))
|
||||
t+block-uuid-sorted-set*
|
||||
(update-t+block-uuid-sorted-set t+block-uuid-sorted-set
|
||||
block-uuid->ops
|
||||
block-uuid->ops*
|
||||
block-uuid)]
|
||||
(recur block-uuid->ops* t+block-uuid-sorted-set* others))))
|
||||
:update
|
||||
(let [already-removed? (some-> (get exist-ops :remove) second (> t))]
|
||||
(if already-removed?
|
||||
(recur block-uuid->ops t+block-uuid-sorted-set others)
|
||||
(let [origin-update-op (get-in block-uuid->ops [block-uuid :update])
|
||||
op* (if origin-update-op (merge-update-ops origin-update-op op) op)
|
||||
block-uuid->ops* (-> block-uuid->ops
|
||||
(assoc-in [block-uuid :update] op*)
|
||||
(update block-uuid dissoc :remove))
|
||||
t+block-uuid-sorted-set*
|
||||
(update-t+block-uuid-sorted-set t+block-uuid-sorted-set
|
||||
block-uuid->ops
|
||||
block-uuid->ops*
|
||||
block-uuid)]
|
||||
(recur block-uuid->ops* t+block-uuid-sorted-set* others))))
|
||||
:remove
|
||||
(let [add-after-remove? (some-> (get exist-ops :move) second (> t))]
|
||||
(if add-after-remove?
|
||||
(recur block-uuid->ops t+block-uuid-sorted-set others)
|
||||
(let [block-uuid->ops* (assoc block-uuid->ops block-uuid {:remove op})
|
||||
t+block-uuid-sorted-set*
|
||||
(update-t+block-uuid-sorted-set t+block-uuid-sorted-set
|
||||
block-uuid->ops
|
||||
block-uuid->ops*
|
||||
block-uuid)]
|
||||
(recur block-uuid->ops* t+block-uuid-sorted-set* others))))
|
||||
:update-page
|
||||
(let [already-removed? (some-> (get exist-ops :remove-page) second (> t))]
|
||||
(if already-removed?
|
||||
(recur block-uuid->ops t+block-uuid-sorted-set others)
|
||||
(let [block-uuid->ops* (-> block-uuid->ops
|
||||
(assoc-in [block-uuid :update-page] op)
|
||||
(update block-uuid dissoc :remove-page))
|
||||
t+block-uuid-sorted-set*
|
||||
(update-t+block-uuid-sorted-set t+block-uuid-sorted-set
|
||||
block-uuid->ops
|
||||
block-uuid->ops*
|
||||
block-uuid)]
|
||||
(recur block-uuid->ops* t+block-uuid-sorted-set* others))))
|
||||
:remove-page
|
||||
(let [add-after-remove? (some-> (get exist-ops :update-page) second (> t))]
|
||||
(if add-after-remove?
|
||||
(recur block-uuid->ops t+block-uuid-sorted-set others)
|
||||
(let [block-uuid->ops* (assoc block-uuid->ops block-uuid {:remove-page op})
|
||||
t+block-uuid-sorted-set*
|
||||
(update-t+block-uuid-sorted-set t+block-uuid-sorted-set
|
||||
block-uuid->ops
|
||||
block-uuid->ops*
|
||||
block-uuid)]
|
||||
(recur block-uuid->ops* t+block-uuid-sorted-set* others)))))))))
|
||||
|
||||
(def ^:private sorted-set-by-t (sorted-set-by (fn [[t1 x] [t2 y]]
|
||||
(let [r (compare t1 t2)]
|
||||
(if (not= r 0)
|
||||
r
|
||||
(compare x y))))))
|
||||
|
||||
(def ^:private empty-ops-store-value {:current-branch {:block-uuid->ops {}
|
||||
:asset-uuid->ops {}
|
||||
:t+block-uuid-sorted-set sorted-set-by-t}})
|
||||
|
||||
(defn init-empty-ops-store!
|
||||
[repo]
|
||||
(swap! *ops-store assoc repo empty-ops-store-value))
|
||||
|
||||
(defn remove-ops-store!
|
||||
[repo]
|
||||
(swap! *ops-store dissoc repo))
|
||||
|
||||
(defn add-ops!
|
||||
[repo ops]
|
||||
(assert (contains? (@*ops-store repo) :current-branch) (@*ops-store repo))
|
||||
(let [ops (ops-coercer ops)
|
||||
{{old-branch-block-uuid->ops :block-uuid->ops
|
||||
old-t+block-uuid-sorted-set :t+block-uuid-sorted-set
|
||||
:as old-branch} :old-branch
|
||||
{:keys [block-uuid->ops t+block-uuid-sorted-set]} :current-branch}
|
||||
(get @*ops-store repo)
|
||||
{:keys [block-uuid->ops t+block-uuid-sorted-set]}
|
||||
(add-ops-aux ops block-uuid->ops t+block-uuid-sorted-set)
|
||||
{old-branch-block-uuid->ops :block-uuid->ops old-t+block-uuid-sorted-set :t+block-uuid-sorted-set}
|
||||
(when old-branch
|
||||
(add-ops-aux ops old-branch-block-uuid->ops old-t+block-uuid-sorted-set))]
|
||||
(swap! *ops-store update repo
|
||||
(fn [{:keys [current-branch old-branch]}]
|
||||
(cond-> {:current-branch
|
||||
(assoc current-branch
|
||||
:block-uuid->ops block-uuid->ops
|
||||
:t+block-uuid-sorted-set t+block-uuid-sorted-set)}
|
||||
old-branch
|
||||
(assoc :old-branch
|
||||
(assoc old-branch
|
||||
:block-uuid->ops old-branch-block-uuid->ops
|
||||
:t+block-uuid-sorted-set old-t+block-uuid-sorted-set)))))))
|
||||
|
||||
(defn update-local-tx!
|
||||
[repo t]
|
||||
(assert (contains? (@*ops-store repo) :current-branch))
|
||||
(swap! *ops-store update-in [repo :current-branch] assoc :local-tx t))
|
||||
|
||||
(defn update-graph-uuid!
|
||||
[repo graph-uuid]
|
||||
(assert (contains? (@*ops-store repo) :current-branch))
|
||||
(swap! *ops-store update repo
|
||||
(fn [{:keys [current-branch old-branch]}]
|
||||
(cond-> {:current-branch (assoc current-branch :graph-uuid graph-uuid)}
|
||||
old-branch (assoc :old-branch (assoc old-branch :graph-uuid graph-uuid))))))
|
||||
|
||||
(defn new-branch!
|
||||
"Make a copy of current repo-ops-store, and also store in `*ops-store`.
|
||||
The following `add-ops` apply on both old-branch and new-branch(current).
|
||||
use `rollback` to replace current-branch with old-branch.
|
||||
use `commit` to remove old-branch."
|
||||
[repo]
|
||||
(let [{:keys [current-branch]} (get @*ops-store repo)]
|
||||
(assert (some? current-branch) repo)
|
||||
(swap! *ops-store assoc-in [repo :old-branch] current-branch)))
|
||||
|
||||
(defn rollback!
|
||||
[repo]
|
||||
(when-let [old-branch (get-in @*ops-store [repo :old-branch])]
|
||||
(assert (some? old-branch))
|
||||
(swap! *ops-store assoc repo {:current-branch old-branch})))
|
||||
|
||||
(defn commit!
|
||||
[repo]
|
||||
(swap! *ops-store update repo dissoc :old-branch))
|
||||
|
||||
(defn get-min-t-block-ops
|
||||
[repo]
|
||||
(let [repo-ops-store (get @*ops-store repo)
|
||||
{:keys [t+block-uuid-sorted-set block-uuid->ops]} (:current-branch repo-ops-store)]
|
||||
(assert (contains? repo-ops-store :current-branch) repo)
|
||||
(when-let [[t block-uuid] (first t+block-uuid-sorted-set)]
|
||||
(if (contains? block-uuid->ops block-uuid)
|
||||
{:block-uuid block-uuid
|
||||
:ops (block-uuid->ops block-uuid)}
|
||||
|
||||
(throw (ex-info "unavailable" {:t t :block-uuid block-uuid :block-uuid->ops block-uuid->ops}))
|
||||
;; if not found, remove item in :t+block-uuid-sorted-set and retry
|
||||
;; (do (swap! *ops-store update-in [repo :current-branch] assoc
|
||||
;; :t+block-uuid-sorted-set (disj t+block-uuid-sorted-set [t block-uuid]))
|
||||
;; (get-min-t-block-ops repo))
|
||||
))))
|
||||
|
||||
(defn get-block-ops
|
||||
[repo block-uuid]
|
||||
(let [repo-ops-store (get @*ops-store repo)
|
||||
{:keys [block-uuid->ops]} (:current-branch repo-ops-store)]
|
||||
(assert (contains? repo-ops-store :current-branch) repo)
|
||||
(block-uuid->ops block-uuid)))
|
||||
|
||||
(defn get-all-ops
|
||||
[repo]
|
||||
(some->> (get @*ops-store repo)
|
||||
:current-branch
|
||||
:block-uuid->ops
|
||||
vals
|
||||
(mapcat vals)))
|
||||
|
||||
(defn get-local-tx
|
||||
[repo]
|
||||
(some-> (get @*ops-store repo)
|
||||
:current-branch
|
||||
:local-tx))
|
||||
|
||||
(defn get-unpushed-block-update-count
|
||||
[repo]
|
||||
(or
|
||||
(some-> (get @*ops-store repo)
|
||||
:current-branch
|
||||
:block-uuid->ops
|
||||
keys
|
||||
count)
|
||||
0))
|
||||
|
||||
(comment
|
||||
(defn get-unpushed-asset-update-count
|
||||
[repo]
|
||||
(some-> (get @*ops-store repo)
|
||||
:current-branch
|
||||
:asset-uuid->ops
|
||||
keys
|
||||
count)))
|
||||
|
||||
(defn intersection-block-uuids
|
||||
[repo block-uuid-coll]
|
||||
(some->> (get @*ops-store repo)
|
||||
:current-branch
|
||||
:block-uuid->ops
|
||||
keys
|
||||
set
|
||||
(set/intersection (set block-uuid-coll))))
|
||||
|
||||
(defn remove-block-ops!
|
||||
[repo block-uuid]
|
||||
{:pre [(uuid? block-uuid)]}
|
||||
(let [repo-ops-store (get @*ops-store repo)
|
||||
{:keys [t+block-uuid-sorted-set block-uuid->ops]} (:current-branch repo-ops-store)]
|
||||
(assert (contains? repo-ops-store :current-branch) repo)
|
||||
(let [min-t (block-uuid->min-t block-uuid->ops block-uuid)]
|
||||
(swap! *ops-store update-in [repo :current-branch] assoc
|
||||
:block-uuid->ops (dissoc block-uuid->ops block-uuid)
|
||||
:t+block-uuid-sorted-set (disj t+block-uuid-sorted-set [min-t block-uuid])))))
|
||||
|
||||
(defn <init-load-from-indexeddb2!
|
||||
[repo]
|
||||
(p/let [v (op-idb-layer/<read2 repo)]
|
||||
(when v
|
||||
(let [v (assoc v
|
||||
:t+block-uuid-sorted-set
|
||||
(apply conj sorted-set-by-t (:t+block-uuid-sorted-set v)))]
|
||||
(swap! *ops-store assoc repo {:current-branch v})
|
||||
(prn ::<init-load-from-indexeddb! repo)))))
|
||||
|
||||
(defn new-task--sync-to-idb
|
||||
[repo]
|
||||
(m/sp
|
||||
(when-let [v (:current-branch (@*ops-store repo))]
|
||||
(m/? (c.m/await-promise (op-idb-layer/<reset2! repo v))))))
|
||||
|
||||
(defn- new-task--sync-to-idb-loop
|
||||
[]
|
||||
(m/sp
|
||||
(let [*v-hash (atom nil)]
|
||||
(loop []
|
||||
(m/? (m/sleep 3000))
|
||||
(let [repo (worker-state/get-current-repo)
|
||||
conn (worker-state/get-datascript-conn repo)]
|
||||
(when (and repo conn
|
||||
(ldb/db-based-graph? @conn))
|
||||
(when-let [v (:current-branch (@*ops-store repo))]
|
||||
(let [v-hash (hash v)]
|
||||
(when (not= v-hash @*v-hash)
|
||||
(m/? (c.m/await-promise (op-idb-layer/<reset2! repo v)))
|
||||
(reset! *v-hash v-hash))))))
|
||||
(recur)))))
|
||||
|
||||
#_:clj-kondo/ignore
|
||||
(defonce _sync-loop-canceler (c.m/run-task (new-task--sync-to-idb-loop) ::sync-to-idb-loop))
|
||||
|
||||
(defn rtc-db-graph?
|
||||
"Is db-graph & RTC enabled"
|
||||
[repo]
|
||||
(and (sqlite-util/db-based-graph? repo)
|
||||
(or (exists? js/process)
|
||||
(some? (get-local-tx repo)))))
|
||||
|
||||
(defn create-pending-ops-count-flow
|
||||
[repo]
|
||||
(m/ap
|
||||
(m/?< (m/watch *ops-store))
|
||||
(try
|
||||
(get-unpushed-block-update-count repo)
|
||||
(catch Cancelled _))))
|
||||
@@ -2,8 +2,7 @@
|
||||
(:require [datascript.core :as d]
|
||||
[frontend.db.conn :as conn]
|
||||
[frontend.test.helper :as test-helper]
|
||||
[frontend.worker.db-listener :as worker-db-listener]
|
||||
[frontend.worker.rtc.op-mem-layer :as op-mem-layer]))
|
||||
[frontend.worker.db-listener :as worker-db-listener]))
|
||||
|
||||
(def listen-test-db-to-gen-rtc-ops-fixture
|
||||
{:before
|
||||
@@ -14,8 +13,3 @@
|
||||
:after
|
||||
#(when-let [test-db-conn (conn/get-db test-helper/test-db-name-db-version false)]
|
||||
(d/unlisten! test-db-conn :frontend.worker.db-listener/listen-db-changes!))})
|
||||
|
||||
(def clear-op-mem-stores-fixture
|
||||
{:before #(do (op-mem-layer/remove-ops-store! test-helper/test-db-name-db-version)
|
||||
(op-mem-layer/init-empty-ops-store! test-helper/test-db-name-db-version))
|
||||
:after #(op-mem-layer/remove-ops-store! test-helper/test-db-name-db-version)})
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
|
||||
(use-fixtures :each
|
||||
test-helper/db-based-start-and-destroy-db-map-fixture
|
||||
rtc-fixture/listen-test-db-to-gen-rtc-ops-fixture
|
||||
rtc-fixture/clear-op-mem-stores-fixture)
|
||||
rtc-fixture/listen-test-db-to-gen-rtc-ops-fixture)
|
||||
|
||||
(deftest local-db-tx->remote-ops-test
|
||||
(let [repo (state/get-current-repo)
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
(ns frontend.worker.rtc.op-mem-layer-test
|
||||
(:require [cljs.test :as t :refer [deftest is testing]]
|
||||
[frontend.worker.rtc.op-mem-layer :as op-layer]
|
||||
[frontend.worker.rtc.fixture :as fixture]
|
||||
[frontend.test.helper :as test-helper]))
|
||||
|
||||
(t/use-fixtures :each fixture/clear-op-mem-stores-fixture)
|
||||
|
||||
(def ^:private repo test-helper/test-db-name-db-version)
|
||||
|
||||
(deftest add-ops!-test
|
||||
(let [block-uuid #uuid "663dd373-41b0-4c59-aa6f-f349eea82609"]
|
||||
(testing "move+update on same block"
|
||||
(let [ops [[:move
|
||||
1
|
||||
{:block-uuid block-uuid}]
|
||||
[:update
|
||||
1
|
||||
{:block-uuid block-uuid,
|
||||
:av-coll
|
||||
[[:block/updated-at "[\"~#'\",1715327859860]" 1 true]
|
||||
[:block/created-at "[\"~#'\",1715327859860]" 1 true]
|
||||
[:block/content "[\"~#'\",\"\"]" 1 true]]}]]]
|
||||
(op-layer/add-ops! repo ops)
|
||||
(is (= {:move
|
||||
[:move
|
||||
1
|
||||
{:block-uuid block-uuid}],
|
||||
:update
|
||||
[:update
|
||||
1
|
||||
{:block-uuid block-uuid,
|
||||
:av-coll
|
||||
[[:block/updated-at "[\"~#'\",1715327859860]" 1 true]
|
||||
[:block/created-at "[\"~#'\",1715327859860]" 1 true]
|
||||
[:block/content "[\"~#'\",\"\"]" 1 true]]}]}
|
||||
(op-layer/get-block-ops repo block-uuid)))))
|
||||
|
||||
(testing "more updates on this block"
|
||||
(let [ops [[:update
|
||||
2
|
||||
{:block-uuid block-uuid,
|
||||
:av-coll
|
||||
[[:block/updated-at "[\"~#'\",1715327859860]" 2 false]
|
||||
[:block/updated-at "[\"~#'\",1715329245395]" 2 true]
|
||||
[:block/content "[\"~#'\",\"\"]" 2 false]
|
||||
[:block/content "[\"~#'\",\"iii\"]" 2 true]]}]
|
||||
[:update
|
||||
3
|
||||
{:block-uuid block-uuid,
|
||||
:av-coll
|
||||
[[:block/tags #uuid "663dd8e0-8840-4411-ab6f-2632ac36bf11" 3 true]]}]]]
|
||||
(op-layer/add-ops! repo ops)
|
||||
(is (=
|
||||
{:move
|
||||
[:move
|
||||
1
|
||||
{:block-uuid block-uuid}],
|
||||
:update
|
||||
[:update
|
||||
3
|
||||
{:block-uuid block-uuid,
|
||||
:av-coll
|
||||
[[:block/updated-at "[\"~#'\",1715327859860]" 1 true]
|
||||
[:block/created-at "[\"~#'\",1715327859860]" 1 true]
|
||||
[:block/content "[\"~#'\",\"\"]" 1 true]
|
||||
[:block/updated-at "[\"~#'\",1715327859860]" 2 false]
|
||||
[:block/updated-at "[\"~#'\",1715329245395]" 2 true]
|
||||
[:block/content "[\"~#'\",\"\"]" 2 false]
|
||||
[:block/content "[\"~#'\",\"iii\"]" 2 true]
|
||||
[:block/tags #uuid "663dd8e0-8840-4411-ab6f-2632ac36bf11" 3 true]]}]}
|
||||
(op-layer/get-block-ops repo block-uuid)))
|
||||
(is (= [1 block-uuid]
|
||||
(first (:t+block-uuid-sorted-set (:current-branch (get @op-layer/*ops-store repo))))))))
|
||||
|
||||
(testing "insert some other blocks"
|
||||
(let [block-uuids (repeatedly 3 random-uuid)
|
||||
ops (map-indexed (fn [idx block-uuid]
|
||||
[:move (+ idx 4) {:block-uuid block-uuid}]) block-uuids)]
|
||||
(op-layer/add-ops! repo ops)
|
||||
(is (= block-uuid (:block-uuid (op-layer/get-min-t-block-ops repo))))))
|
||||
|
||||
(testing "remove this block"
|
||||
(let [ops [[:remove 999 {:block-uuid block-uuid}]]]
|
||||
(op-layer/add-ops! repo ops)
|
||||
(is (=
|
||||
{:remove [:remove 999 {:block-uuid block-uuid}]}
|
||||
(op-layer/get-block-ops repo block-uuid)))))))
|
||||
@@ -6,8 +6,6 @@
|
||||
[frontend.test.helper :as test-helper]
|
||||
[frontend.worker.rtc.const :as rtc-const]
|
||||
[frontend.worker.rtc.remote-update :as r.remote]
|
||||
[frontend.worker.rtc.client :as r.client]
|
||||
[frontend.worker.rtc.op-mem-layer :as op-mem-layer]
|
||||
[frontend.worker.state :as worker-state]
|
||||
[logseq.common.config :as common-config]
|
||||
[logseq.db :as ldb]
|
||||
@@ -82,44 +80,44 @@
|
||||
:block/content "update content"}}
|
||||
r)))))
|
||||
|
||||
(deftest gen-remote-ops-test
|
||||
(let [repo (state/get-current-repo)
|
||||
conn (conn/get-db repo false)
|
||||
[uuid1 uuid2 uuid3 uuid4] (repeatedly random-uuid)
|
||||
opts {:persist-op? false
|
||||
:transact-opts {:repo repo
|
||||
:conn conn}}]
|
||||
(test-helper/create-page! "gen-remote-ops-test" {:redirect? false :create-first-block? false :uuid uuid1})
|
||||
(outliner-tx/transact!
|
||||
opts
|
||||
(outliner-core/insert-blocks!
|
||||
repo
|
||||
conn
|
||||
[{:block/uuid uuid2 :block/content "uuid2-block"}
|
||||
{:block/uuid uuid3 :block/content "uuid3-block"
|
||||
:block/parent [:block/uuid uuid1]}
|
||||
{:block/uuid uuid4 :block/content "uuid4-block"
|
||||
:block/parent [:block/uuid uuid1]}]
|
||||
(ldb/get-page @conn "gen-remote-ops-test")
|
||||
{:sibling? true :keep-uuid? true}))
|
||||
;; (deftest gen-remote-ops-test
|
||||
;; (let [repo (state/get-current-repo)
|
||||
;; conn (conn/get-db repo false)
|
||||
;; [uuid1 uuid2 uuid3 uuid4] (repeatedly random-uuid)
|
||||
;; opts {:persist-op? false
|
||||
;; :transact-opts {:repo repo
|
||||
;; :conn conn}}]
|
||||
;; (test-helper/create-page! "gen-remote-ops-test" {:redirect? false :create-first-block? false :uuid uuid1})
|
||||
;; (outliner-tx/transact!
|
||||
;; opts
|
||||
;; (outliner-core/insert-blocks!
|
||||
;; repo
|
||||
;; conn
|
||||
;; [{:block/uuid uuid2 :block/content "uuid2-block"}
|
||||
;; {:block/uuid uuid3 :block/content "uuid3-block"
|
||||
;; :block/parent [:block/uuid uuid1]}
|
||||
;; {:block/uuid uuid4 :block/content "uuid4-block"
|
||||
;; :block/parent [:block/uuid uuid1]}]
|
||||
;; (ldb/get-page @conn "gen-remote-ops-test")
|
||||
;; {:sibling? true :keep-uuid? true}))
|
||||
|
||||
(op-mem-layer/init-empty-ops-store! repo)
|
||||
(op-mem-layer/add-ops! repo [[:move 1 {:block-uuid uuid2}]
|
||||
[:move 2 {:block-uuid uuid4}]
|
||||
[:move 3 {:block-uuid uuid3}]
|
||||
[:update 4 {:block-uuid uuid4
|
||||
:av-coll [[:block/content (ldb/write-transit-str "uuid4-block") 4 true]]}]])
|
||||
(let [_ (op-mem-layer/new-branch! repo)
|
||||
r1 (#'r.client/gen-block-uuid->remote-ops repo conn :n 1)
|
||||
_ (op-mem-layer/rollback! repo)
|
||||
r2 (#'r.client/gen-block-uuid->remote-ops repo conn :n 3)]
|
||||
(is (= {uuid2 [:move]}
|
||||
(update-vals r1 keys)))
|
||||
(is (= {uuid2 [:move]
|
||||
uuid3 [:move]
|
||||
uuid4 [:move :update]}
|
||||
(update-vals r2 keys))))
|
||||
(op-mem-layer/remove-ops-store! repo)))
|
||||
;; (op-mem-layer/init-empty-ops-store! repo)
|
||||
;; (op-mem-layer/add-ops! repo [[:move 1 {:block-uuid uuid2}]
|
||||
;; [:move 2 {:block-uuid uuid4}]
|
||||
;; [:move 3 {:block-uuid uuid3}]
|
||||
;; [:update 4 {:block-uuid uuid4
|
||||
;; :av-coll [[:block/content (ldb/write-transit-str "uuid4-block") 4 true]]}]])
|
||||
;; (let [_ (op-mem-layer/new-branch! repo)
|
||||
;; r1 (#'r.client/gen-block-uuid->remote-ops repo conn :n 1)
|
||||
;; _ (op-mem-layer/rollback! repo)
|
||||
;; r2 (#'r.client/gen-block-uuid->remote-ops repo conn :n 3)]
|
||||
;; (is (= {uuid2 [:move]}
|
||||
;; (update-vals r1 keys)))
|
||||
;; (is (= {uuid2 [:move]
|
||||
;; uuid3 [:move]
|
||||
;; uuid4 [:move :update]}
|
||||
;; (update-vals r2 keys))))
|
||||
;; (op-mem-layer/remove-ops-store! repo)))
|
||||
|
||||
(deftest ^:fix-me apply-remote-move-ops-test
|
||||
(let [repo (state/get-current-repo)
|
||||
|
||||
Reference in New Issue
Block a user