|
|
@@ -1,89 +1,68 @@
|
|
|
(ns frontend.worker.rtc.op-mem-layer
|
|
|
"Store client-ops in memory.
|
|
|
And sync these ops to indexedDb automatically."
|
|
|
- (:require [clojure.core.async :as async :refer [<! go-loop timeout]]
|
|
|
- [clojure.set :as set]
|
|
|
+ (: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]
|
|
|
- [malli.core :as m]
|
|
|
+ [logseq.db :as ldb]
|
|
|
+ [logseq.db.sqlite.util :as sqlite-util]
|
|
|
+ [malli.core :as ma]
|
|
|
[malli.transform :as mt]
|
|
|
- [promesa.core :as p]
|
|
|
- [logseq.db.sqlite.util :as sqlite-util]))
|
|
|
+ [missionary.core :as m]
|
|
|
+ [promesa.core :as p]))
|
|
|
|
|
|
(def op-schema
|
|
|
[:multi {:dispatch first}
|
|
|
- ["move"
|
|
|
+ [:move
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
- [:block-uuid :uuid]
|
|
|
- [:epoch :int]]]]]
|
|
|
- ["remove"
|
|
|
+ [:block-uuid :uuid]]]]]
|
|
|
+ [:remove
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
- [:block-uuid :uuid]
|
|
|
- [:epoch :int]]]]]
|
|
|
- ["update"
|
|
|
+ [:block-uuid :uuid]]]]]
|
|
|
+ [:update-page
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
- [:block-uuid :uuid]
|
|
|
- [:updated-attrs {:optional true}
|
|
|
- [:map {:closed true}
|
|
|
- [:schema {:optional true} :nil]
|
|
|
- [:content {:optional true} :nil]
|
|
|
- [:link {:optional true} :nil]
|
|
|
- [:journal-day {:optional true} :nil]
|
|
|
- [:alias {:optional true} [:map
|
|
|
- [:add {:optional true} [:set :uuid]]
|
|
|
- [:retract {:optional true} [:set :uuid]]]]
|
|
|
- [:type {:optional true} [:map
|
|
|
- [:add {:optional true} [:set :string]]
|
|
|
- [:retract {:optional true} [:set :string]]]]
|
|
|
- [:tags {:optional true} [:map
|
|
|
- [:add {:optional true} [:set :uuid]]
|
|
|
- [:retract {:optional true} [:set :uuid]]]]
|
|
|
- [:properties {:optional true} [:map
|
|
|
- [:add {:optional true} [:set :uuid]]
|
|
|
- [:retract {:optional true} [:set :uuid]]]]]]
|
|
|
- [:epoch :int]]]]]
|
|
|
- ["update-page"
|
|
|
+ [:block-uuid :uuid]]]]]
|
|
|
+ [:remove-page
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
- [:block-uuid :uuid]
|
|
|
- [:epoch :int]]]]]
|
|
|
- ["remove-page"
|
|
|
+ [:block-uuid :uuid]]]]]
|
|
|
+ [:update
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
[:block-uuid :uuid]
|
|
|
- [:epoch :int]]]]]
|
|
|
- ["update-asset"
|
|
|
+ [:av-coll [:sequential rtc-const/av-schema]]]]]]
|
|
|
+
|
|
|
+ [:update-asset
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
- [:asset-uuid :uuid]
|
|
|
- [:epoch :int]]]]]
|
|
|
- ["remove-asset"
|
|
|
+ [:asset-uuid :uuid]]]]]
|
|
|
+ [:remove-asset
|
|
|
[:catn
|
|
|
- [:op :string]
|
|
|
+ [:op :keyword]
|
|
|
+ [:t :int]
|
|
|
[:value [:map
|
|
|
- [:asset-uuid :uuid]
|
|
|
- [:epoch :int]]]]]])
|
|
|
+ [:asset-uuid :uuid]]]]]])
|
|
|
|
|
|
(def ops-schema [:sequential op-schema])
|
|
|
|
|
|
-(def ops-from-store-schema [:sequential [:catn
|
|
|
- [:key :int]
|
|
|
- [:op op-schema]]])
|
|
|
-
|
|
|
-(def ops-from-store-coercer (m/coercer ops-from-store-schema mt/json-transformer))
|
|
|
-(def ops-validator (m/validator ops-schema))
|
|
|
-(def ops-coercer (m/coercer ops-schema mt/json-transformer))
|
|
|
-(def ops-encoder (m/encoder ops-schema mt/json-transformer))
|
|
|
-
|
|
|
+(def ops-coercer (ma/coercer ops-schema mt/json-transformer))
|
|
|
|
|
|
(def ops-store-value-schema
|
|
|
[:map
|
|
|
@@ -93,8 +72,7 @@
|
|
|
[:map-of [:enum :move :remove :update :update-page :remove-page] :any]]]
|
|
|
[:asset-uuid->ops [:map-of :uuid
|
|
|
[:map-of [:enum :update-asset :remove-asset] :any]]]
|
|
|
- [:epoch->block-uuid-sorted-map [:map-of :int :uuid]]
|
|
|
- [:epoch->asset-uuid-sorted-map [:map-of :int :uuid]]])
|
|
|
+ [:t+block-uuid-sorted-set [:set [:cat :int :uuid]]]])
|
|
|
|
|
|
(def ops-store-schema
|
|
|
[:map-of :string ; repo-name
|
|
|
@@ -102,190 +80,127 @@
|
|
|
[:current-branch ops-store-value-schema]
|
|
|
[:old-branch {:optional true} [:maybe ops-store-value-schema]]]])
|
|
|
|
|
|
-(def ops-store-schema-coercer (m/coercer ops-store-schema))
|
|
|
-
|
|
|
+(def ops-store-schema-coercer (ma/coercer ops-store-schema))
|
|
|
|
|
|
(defonce *ops-store (atom {} :validator ops-store-schema-coercer))
|
|
|
|
|
|
-(defn- merge-add-retract-maps
|
|
|
- [m1 m2]
|
|
|
- (let [{add1 :add retract1 :retract} m1
|
|
|
- {add2 :add retract2 :retract} m2
|
|
|
- add (set/union (set/difference add1 retract2) add2)
|
|
|
- retract (set/union (set/difference retract1 add2) retract2)]
|
|
|
- (when (or (seq add) (seq retract))
|
|
|
- (cond-> {}
|
|
|
- (seq add) (assoc :add add)
|
|
|
- (seq retract) (assoc :retract retract)))))
|
|
|
-
|
|
|
(defn- merge-update-ops
|
|
|
- "op2-epoch > op1-epoch"
|
|
|
[update-op1 update-op2]
|
|
|
- {:pre [(= "update" (first update-op1))
|
|
|
- (= "update" (first update-op2))
|
|
|
- (= (:block-uuid (second update-op1))
|
|
|
- (:block-uuid (second update-op2)))]}
|
|
|
- (let [epoch1 (:epoch (second update-op1))
|
|
|
- epoch2 (:epoch (second update-op2))]
|
|
|
- (if (> epoch1 epoch2)
|
|
|
+ {: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 [updated-attrs1 (:updated-attrs (second update-op1))
|
|
|
- updated-attrs2 (:updated-attrs (second update-op2))
|
|
|
- alias (merge-add-retract-maps (:alias updated-attrs1) (:alias updated-attrs2))
|
|
|
- type (merge-add-retract-maps (:type updated-attrs1) (:type updated-attrs2))
|
|
|
- tags (merge-add-retract-maps (:tags updated-attrs1) (:tags updated-attrs2))
|
|
|
- properties (merge-add-retract-maps (:properties updated-attrs1) (:properties updated-attrs2))
|
|
|
- updated-attrs
|
|
|
- (cond-> (merge (select-keys updated-attrs1 [:schema :content :link])
|
|
|
- (select-keys updated-attrs2 [:schema :content :link]))
|
|
|
- alias (assoc :alias alias)
|
|
|
- type (assoc :type type)
|
|
|
- tags (assoc :tags tags)
|
|
|
- properties (assoc :properties properties))]
|
|
|
-
|
|
|
- ["update" {:block-uuid (:block-uuid (second update-op1))
|
|
|
- :updated-attrs updated-attrs
|
|
|
- :epoch epoch2}]))))
|
|
|
-
|
|
|
-(defn- block-uuid->min-epoch
|
|
|
+ (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 (comp :epoch second))
|
|
|
+ (map second)
|
|
|
seq
|
|
|
(apply min)))
|
|
|
|
|
|
-(defn- asset-uuid->min-epoch
|
|
|
- [asset-uuid->ops asset-uuid]
|
|
|
- (block-uuid->min-epoch asset-uuid->ops asset-uuid))
|
|
|
+(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 epoch->block-uuid-sorted-map asset-uuid->ops epoch->asset-uuid-sorted-map]
|
|
|
+ [ops block-uuid->ops t+block-uuid-sorted-set]
|
|
|
(loop [block-uuid->ops block-uuid->ops
|
|
|
- epoch->block-uuid-sorted-map epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops asset-uuid->ops
|
|
|
- epoch->asset-uuid-sorted-map epoch->asset-uuid-sorted-map
|
|
|
+ t+block-uuid-sorted-set t+block-uuid-sorted-set
|
|
|
[op & others] ops]
|
|
|
(if-not op
|
|
|
{:block-uuid->ops block-uuid->ops
|
|
|
- :asset-uuid->ops asset-uuid->ops
|
|
|
- :epoch->block-uuid-sorted-map epoch->block-uuid-sorted-map
|
|
|
- :epoch->asset-uuid-sorted-map epoch->asset-uuid-sorted-map}
|
|
|
- (let [[op-type value] op
|
|
|
- {:keys [block-uuid asset-uuid epoch]} value
|
|
|
- exist-ops (some-> block-uuid block-uuid->ops)
|
|
|
- exist-asset-ops (some-> asset-uuid asset-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 :epoch (> epoch))]
|
|
|
+ :move
|
|
|
+ (let [already-removed? (some-> (get exist-ops :remove) second (> t))]
|
|
|
(if already-removed?
|
|
|
- (recur block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
+ (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))
|
|
|
- origin-min-epoch (block-uuid->min-epoch block-uuid->ops block-uuid)
|
|
|
- min-epoch (block-uuid->min-epoch block-uuid->ops* block-uuid)]
|
|
|
- (recur (-> block-uuid->ops
|
|
|
- (assoc-in [block-uuid :move] op)
|
|
|
- (update block-uuid dissoc :remove))
|
|
|
- (-> epoch->block-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch block-uuid))
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others))))
|
|
|
- "update"
|
|
|
- (let [already-removed? (some-> (get exist-ops :remove) second :epoch (> epoch))]
|
|
|
+ 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 epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
+ (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))
|
|
|
- origin-min-epoch (block-uuid->min-epoch block-uuid->ops block-uuid)
|
|
|
- min-epoch (block-uuid->min-epoch block-uuid->ops* block-uuid)]
|
|
|
- (recur block-uuid->ops*
|
|
|
- (-> epoch->block-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch block-uuid))
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others))))
|
|
|
- "remove"
|
|
|
- (let [add-after-remove? (some-> (get exist-ops :move) second :epoch (> epoch))]
|
|
|
+ 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 epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
+ (recur block-uuid->ops t+block-uuid-sorted-set others)
|
|
|
(let [block-uuid->ops* (assoc block-uuid->ops block-uuid {:remove op})
|
|
|
- origin-min-epoch (block-uuid->min-epoch block-uuid->ops block-uuid)
|
|
|
- min-epoch (block-uuid->min-epoch block-uuid->ops* block-uuid)]
|
|
|
- (recur block-uuid->ops*
|
|
|
- (-> epoch->block-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch block-uuid))
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others))))
|
|
|
- "update-page"
|
|
|
- (let [already-removed? (some-> (get exist-ops :remove-page) second :epoch (> epoch))]
|
|
|
+ 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 epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
+ (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))
|
|
|
- origin-min-epoch (block-uuid->min-epoch block-uuid->ops block-uuid)
|
|
|
- min-epoch (block-uuid->min-epoch block-uuid->ops* block-uuid)]
|
|
|
- (recur block-uuid->ops*
|
|
|
- (-> epoch->block-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch block-uuid))
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others))))
|
|
|
- "remove-page"
|
|
|
- (let [add-after-remove? (some-> (get exist-ops :update-page) second :epoch (> epoch))]
|
|
|
+ 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 epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
+ (recur block-uuid->ops t+block-uuid-sorted-set others)
|
|
|
(let [block-uuid->ops* (assoc block-uuid->ops block-uuid {:remove-page op})
|
|
|
- origin-min-epoch (block-uuid->min-epoch block-uuid->ops block-uuid)
|
|
|
- min-epoch (block-uuid->min-epoch block-uuid->ops* block-uuid)]
|
|
|
- (recur block-uuid->ops*
|
|
|
- (-> epoch->block-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch block-uuid))
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others))))
|
|
|
- "update-asset"
|
|
|
- (let [already-removed? (some-> (get exist-asset-ops :remove-asset) second :epoch (> epoch))]
|
|
|
- (if already-removed?
|
|
|
- (recur block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
- (let [asset-uuid->ops* (assoc asset-uuid->ops asset-uuid {:update-asset op})
|
|
|
- origin-min-epoch (asset-uuid->min-epoch asset-uuid->ops asset-uuid)
|
|
|
- min-epoch (asset-uuid->min-epoch asset-uuid->ops* asset-uuid)]
|
|
|
- (recur block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops*
|
|
|
- (-> epoch->asset-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch asset-uuid))
|
|
|
- others))))
|
|
|
- "remove-asset"
|
|
|
- (let [add-after-remove? (some-> (get exist-asset-ops :update-asset) second :epoch (> epoch))]
|
|
|
- (if add-after-remove?
|
|
|
- (recur block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map others)
|
|
|
- (let [asset-uuid->ops* (assoc asset-uuid->ops asset-uuid {:remove-asset op})
|
|
|
- origin-min-epoch (asset-uuid->min-epoch asset-uuid->ops asset-uuid)
|
|
|
- min-epoch (asset-uuid->min-epoch asset-uuid->ops* asset-uuid)]
|
|
|
- (recur block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops*
|
|
|
- (-> epoch->asset-uuid-sorted-map
|
|
|
- (dissoc origin-min-epoch)
|
|
|
- (assoc min-epoch asset-uuid))
|
|
|
- others))))
|
|
|
- )))))
|
|
|
-
|
|
|
-
|
|
|
-(def empty-ops-store-value {:current-branch {:block-uuid->ops {}
|
|
|
- :epoch->block-uuid-sorted-map (sorted-map-by <)
|
|
|
- :asset-uuid->ops {}
|
|
|
- :epoch->asset-uuid-sorted-map (sorted-map-by <)}})
|
|
|
+ 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]
|
|
|
@@ -300,62 +215,26 @@
|
|
|
(assert (contains? (@*ops-store repo) :current-branch) (@*ops-store repo))
|
|
|
(let [ops (ops-coercer ops)
|
|
|
{{old-branch-block-uuid->ops :block-uuid->ops
|
|
|
- old-epoch->block-uuid-sorted-map :epoch->block-uuid-sorted-map
|
|
|
- old-branch-asset-uuid->ops :asset-uuid->ops
|
|
|
- old-epoch->asset-uuid-sorted-map :epoch->asset-uuid-sorted-map
|
|
|
+ old-t+block-uuid-sorted-set :t+block-uuid-sorted-set
|
|
|
:as old-branch} :old-branch
|
|
|
- {:keys [block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map]} :current-branch}
|
|
|
+ {:keys [block-uuid->ops t+block-uuid-sorted-set]} :current-branch}
|
|
|
(get @*ops-store repo)
|
|
|
- {:keys [block-uuid->ops epoch->block-uuid-sorted-map]}
|
|
|
- (add-ops-aux ops block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map)
|
|
|
- {old-branch-block-uuid->ops :block-uuid->ops old-epoch->block-uuid-sorted-map :epoch->block-uuid-sorted-map}
|
|
|
+ {: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-epoch->block-uuid-sorted-map
|
|
|
- old-branch-asset-uuid->ops old-epoch->asset-uuid-sorted-map))]
|
|
|
+ (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
|
|
|
- :epoch->block-uuid-sorted-map epoch->block-uuid-sorted-map)}
|
|
|
+ :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
|
|
|
- :epoch->block-uuid-sorted-map old-epoch->block-uuid-sorted-map)))))))
|
|
|
-
|
|
|
-(defn add-asset-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-epoch->block-uuid-sorted-map :epoch->block-uuid-sorted-map
|
|
|
- old-branch-asset-uuid->ops :asset-uuid->ops
|
|
|
- old-epoch->asset-uuid-sorted-map :epoch->asset-uuid-sorted-map
|
|
|
- :as old-branch} :old-branch
|
|
|
- {:keys [block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map]} :current-branch}
|
|
|
- (get @*ops-store repo)
|
|
|
- {:keys [asset-uuid->ops epoch->asset-uuid-sorted-map]}
|
|
|
- (add-ops-aux ops block-uuid->ops epoch->block-uuid-sorted-map
|
|
|
- asset-uuid->ops epoch->asset-uuid-sorted-map)
|
|
|
- {old-branch-asset-uuid->ops :asset-uuid->ops old-epoch->asset-uuid-sorted-map :epoch->asset-uuid-sorted-map}
|
|
|
- (when old-branch
|
|
|
- (add-ops-aux ops old-branch-block-uuid->ops old-epoch->block-uuid-sorted-map
|
|
|
- old-branch-asset-uuid->ops old-epoch->asset-uuid-sorted-map))]
|
|
|
- (swap! *ops-store update repo
|
|
|
- (fn [{:keys [current-branch old-branch]}]
|
|
|
- (cond-> {:current-branch
|
|
|
- (assoc current-branch
|
|
|
- :asset-uuid->ops asset-uuid->ops
|
|
|
- :epoch->asset-uuid-sorted-map epoch->asset-uuid-sorted-map)}
|
|
|
- old-branch
|
|
|
- (assoc :old-branch
|
|
|
- (assoc old-branch
|
|
|
- :asset-uuid->ops old-branch-asset-uuid->ops
|
|
|
- :epoch->asset-uuid-sorted-map old-epoch->asset-uuid-sorted-map)))))))
|
|
|
+ :t+block-uuid-sorted-set old-t+block-uuid-sorted-set)))))))
|
|
|
|
|
|
(defn update-local-tx!
|
|
|
[repo t]
|
|
|
@@ -390,16 +269,22 @@
|
|
|
[repo]
|
|
|
(swap! *ops-store update repo dissoc :old-branch))
|
|
|
|
|
|
-
|
|
|
-(defn get-min-epoch-block-ops
|
|
|
+(defn get-min-t-block-ops
|
|
|
[repo]
|
|
|
(let [repo-ops-store (get @*ops-store repo)
|
|
|
- {:keys [epoch->block-uuid-sorted-map block-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
+ {:keys [t+block-uuid-sorted-set block-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
(assert (contains? repo-ops-store :current-branch) repo)
|
|
|
- (when-let [[_epoch block-uuid] (first epoch->block-uuid-sorted-map)]
|
|
|
- (assert (contains? block-uuid->ops block-uuid))
|
|
|
- {:block-uuid block-uuid
|
|
|
- :ops (block-uuid->ops block-uuid)})))
|
|
|
+ (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]
|
|
|
@@ -416,25 +301,6 @@
|
|
|
vals
|
|
|
(mapcat vals)))
|
|
|
|
|
|
-(comment
|
|
|
- (defn get-min-epoch-asset-ops
|
|
|
- [repo]
|
|
|
- (let [repo-ops-store (get @*ops-store repo)
|
|
|
- {:keys [epoch->asset-uuid-sorted-map asset-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
- (assert (contains? repo-ops-store :current-branch) repo)
|
|
|
- (when-let [[_epoch asset-uuid] (first epoch->asset-uuid-sorted-map)]
|
|
|
- (assert (contains? asset-uuid->ops asset-uuid))
|
|
|
- {:asset-uuid asset-uuid
|
|
|
- :ops (asset-uuid->ops asset-uuid)}))))
|
|
|
-
|
|
|
-(comment
|
|
|
- (defn get-asset-ops
|
|
|
- [repo asset-uuid]
|
|
|
- (let [repo-ops-store (get @*ops-store repo)
|
|
|
- {:keys [asset-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
- (assert (contains? repo-ops-store :current-branch) repo)
|
|
|
- (asset-uuid->ops asset-uuid))))
|
|
|
-
|
|
|
(defn get-local-tx
|
|
|
[repo]
|
|
|
(some-> (get @*ops-store repo)
|
|
|
@@ -469,78 +335,53 @@
|
|
|
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 [epoch->block-uuid-sorted-map block-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
+ {:keys [t+block-uuid-sorted-set block-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
(assert (contains? repo-ops-store :current-branch) repo)
|
|
|
- (let [min-epoch (block-uuid->min-epoch block-uuid->ops block-uuid)]
|
|
|
+ (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)
|
|
|
- :epoch->block-uuid-sorted-map (dissoc epoch->block-uuid-sorted-map min-epoch)))))
|
|
|
+ :t+block-uuid-sorted-set (disj t+block-uuid-sorted-set [min-t block-uuid])))))
|
|
|
|
|
|
-(comment
|
|
|
- (defn remove-asset-ops!
|
|
|
- [repo asset-uuid]
|
|
|
- {:pre [(uuid? asset-uuid)]}
|
|
|
- (let [repo-ops-store (get @*ops-store repo)
|
|
|
- {:keys [epoch->asset-uuid-sorted-map asset-uuid->ops]} (:current-branch repo-ops-store)]
|
|
|
- (assert (contains? repo-ops-store :current-branch) repo)
|
|
|
- (let [min-epoch (asset-uuid->min-epoch asset-uuid->ops asset-uuid)]
|
|
|
- (swap! *ops-store update-in [repo :current-branch] assoc
|
|
|
- :asset-uuid->ops (dissoc asset-uuid->ops asset-uuid)
|
|
|
- :epoch->asset-uuid-sorted-map (dissoc epoch->asset-uuid-sorted-map min-epoch))))))
|
|
|
-
|
|
|
-
|
|
|
-(defn <init-load-from-indexeddb!
|
|
|
+
|
|
|
+(defn <init-load-from-indexeddb2!
|
|
|
[repo]
|
|
|
- (p/let [all-data (op-idb-layer/<read repo)
|
|
|
- all-data-m (into {} all-data)
|
|
|
- local-tx (get all-data-m "local-tx")]
|
|
|
- (when local-tx
|
|
|
- (let [graph-uuid (get all-data-m "graph-uuid")
|
|
|
- ops (->> all-data
|
|
|
- (filter (comp number? first))
|
|
|
- (sort-by first <)
|
|
|
- ops-from-store-coercer
|
|
|
- (map second))
|
|
|
- {:keys [block-uuid->ops epoch->block-uuid-sorted-map asset-uuid->ops epoch->asset-uuid-sorted-map]}
|
|
|
- (add-ops-aux ops {} (sorted-map-by <) {} (sorted-map-by <))
|
|
|
- r (cond-> {:block-uuid->ops block-uuid->ops
|
|
|
- :epoch->block-uuid-sorted-map epoch->block-uuid-sorted-map
|
|
|
- :asset-uuid->ops asset-uuid->ops
|
|
|
- :epoch->asset-uuid-sorted-map epoch->asset-uuid-sorted-map}
|
|
|
- graph-uuid (assoc :graph-uuid graph-uuid)
|
|
|
- local-tx (assoc :local-tx local-tx))]
|
|
|
- (assert (ops-validator ops) ops)
|
|
|
- (swap! *ops-store update repo #(-> %
|
|
|
- (assoc :current-branch r)
|
|
|
- (dissoc :old-branch)))
|
|
|
+ (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 <sync-to-idb-layer!
|
|
|
+(defn new-task--sync-to-idb
|
|
|
[repo]
|
|
|
- (let [repo-ops-store (get @*ops-store repo)
|
|
|
- {:keys [block-uuid->ops local-tx graph-uuid]} (:current-branch repo-ops-store)
|
|
|
- ops (mapcat vals (vals block-uuid->ops))
|
|
|
- ops* (ops-encoder ops)]
|
|
|
- (op-idb-layer/<reset! repo ops* graph-uuid local-tx)))
|
|
|
+ (m/sp
|
|
|
+ (when-let [v (:current-branch (@*ops-store repo))]
|
|
|
+ (m/? (c.m/await-promise (op-idb-layer/<reset2! repo v))))))
|
|
|
|
|
|
-(defn run-sync-loop
|
|
|
+(defn- new-task--sync-to-idb-loop
|
|
|
[]
|
|
|
- (go-loop []
|
|
|
- (<! (timeout 3000))
|
|
|
- (when-let [repo (worker-state/get-current-repo)]
|
|
|
- (when (and (sqlite-util/db-based-graph? repo)
|
|
|
- (contains? (@*ops-store repo) :current-branch))
|
|
|
- (<! (<sync-to-idb-layer! repo))))
|
|
|
- (recur)))
|
|
|
+ (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 (run-sync-loop))
|
|
|
-
|
|
|
+(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"
|