mirror of
https://github.com/logseq/logseq.git
synced 2026-04-25 06:35:02 +00:00
fix: more lint error
This commit is contained in:
1
deps/common/.clj-kondo/config.edn
vendored
1
deps/common/.clj-kondo/config.edn
vendored
@@ -6,5 +6,6 @@
|
|||||||
|
|
||||||
:consistent-alias
|
:consistent-alias
|
||||||
{:aliases {clojure.string string}}}
|
{:aliases {clojure.string string}}}
|
||||||
|
:lint-as {promesa.core/let clojure.core/let}
|
||||||
:skip-comments true
|
:skip-comments true
|
||||||
:output {:progress true}}
|
:output {:progress true}}
|
||||||
|
|||||||
92
deps/common/src/logseq/common/authorization.cljs
vendored
92
deps/common/src/logseq/common/authorization.cljs
vendored
@@ -41,22 +41,22 @@
|
|||||||
(defn- get-jwks-keys
|
(defn- get-jwks-keys
|
||||||
[url & {:keys [force?]}]
|
[url & {:keys [force?]}]
|
||||||
(let [now (get-now-ms)
|
(let [now (get-now-ms)
|
||||||
{:keys [url cached-url keys fetched-at]} {:cached-url (:url @*jwks-cache)
|
{:keys [url cached-url jwks-keys fetched-at]} {:cached-url (:url @*jwks-cache)
|
||||||
:url url
|
:url url
|
||||||
:keys (:keys @*jwks-cache)
|
:jwks-keys (:keys @*jwks-cache)
|
||||||
:fetched-at (:fetched-at @*jwks-cache)}
|
:fetched-at (:fetched-at @*jwks-cache)}
|
||||||
fresh? (and (not force?)
|
fresh? (and (not force?)
|
||||||
(= cached-url url)
|
(= cached-url url)
|
||||||
keys
|
jwks-keys
|
||||||
(< (- now fetched-at) jwks-ttl-ms))]
|
(< (- now fetched-at) jwks-ttl-ms))]
|
||||||
(if fresh?
|
(if fresh?
|
||||||
(p/resolved keys)
|
(p/resolved jwks-keys)
|
||||||
(p/let [jwks-resp (js/fetch url)
|
(p/let [jwks-resp (js/fetch url)
|
||||||
_ (when-not (.-ok jwks-resp) (throw (ex-info "jwks" {})))
|
_ (when-not (.-ok jwks-resp) (throw (ex-info "jwks" {})))
|
||||||
jwks (.json jwks-resp)
|
jwks (.json jwks-resp)
|
||||||
keys (or (aget jwks "keys") #js [])]
|
jwks-keys (or (aget jwks "keys") #js [])]
|
||||||
(reset! *jwks-cache {:url url :keys keys :fetched-at now})
|
(reset! *jwks-cache {:url url :keys jwks-keys :fetched-at now})
|
||||||
keys))))
|
jwks-keys))))
|
||||||
|
|
||||||
(defn- base64url->uint8array [input]
|
(defn- base64url->uint8array [input]
|
||||||
(let [pad (if (pos? (mod (count input) 4))
|
(let [pad (if (pos? (mod (count input) 4))
|
||||||
@@ -84,40 +84,40 @@
|
|||||||
#js ["verify"]))
|
#js ["verify"]))
|
||||||
|
|
||||||
(defn verify-jwt [token env]
|
(defn verify-jwt [token env]
|
||||||
(let [parts (string/split token #"\.")
|
(let [parts (string/split token #"\.")]
|
||||||
_ (when (not= 3 (count parts)) (throw (ex-info "invalid" {})))
|
(when (not= 3 (count parts)) (throw (ex-info "invalid" {})))
|
||||||
header-part (nth parts 0)
|
(let [header-part (nth parts 0)
|
||||||
payload-part (nth parts 1)
|
payload-part (nth parts 1)
|
||||||
signature-part (nth parts 2)
|
signature-part (nth parts 2)
|
||||||
now-ms (get-now-ms)
|
now-ms (get-now-ms)
|
||||||
now-s (js/Math.floor (/ now-ms 1000))]
|
now-s (js/Math.floor (/ now-ms 1000))]
|
||||||
(if-let [cached (cached-token token now-s now-ms)]
|
(if-let [cached (cached-token token now-s now-ms)]
|
||||||
(p/resolved cached)
|
(p/resolved cached)
|
||||||
(p/let [header (decode-jwt-part header-part)
|
(p/let [header (decode-jwt-part header-part)
|
||||||
payload (decode-jwt-part payload-part)
|
payload (decode-jwt-part payload-part)
|
||||||
issuer (aget env "COGNITO_ISSUER")
|
issuer (aget env "COGNITO_ISSUER")
|
||||||
client-id (aget env "COGNITO_CLIENT_ID")
|
client-id (aget env "COGNITO_CLIENT_ID")
|
||||||
_ (when (not= (aget payload "iss") issuer) (throw (ex-info "iss not found" {})))
|
_ (when (not= (aget payload "iss") issuer) (throw (ex-info "iss not found" {})))
|
||||||
_ (when (not= (aget payload "aud") client-id) (throw (ex-info "aud not found" {})))
|
_ (when (not= (aget payload "aud") client-id) (throw (ex-info "aud not found" {})))
|
||||||
_ (when (and (aget payload "exp") (< (aget payload "exp") now-s))
|
_ (when (and (aget payload "exp") (< (aget payload "exp") now-s))
|
||||||
(throw (ex-info "exp" {})))
|
(throw (ex-info "exp" {})))
|
||||||
jwks-url (aget env "COGNITO_JWKS_URL")
|
jwks-url (aget env "COGNITO_JWKS_URL")
|
||||||
keys (get-jwks-keys jwks-url)
|
jwks-keys (get-jwks-keys jwks-url)
|
||||||
key (.find keys (fn [k] (= (aget k "kid") (aget header "kid"))))
|
matching-key (.find jwks-keys (fn [k] (= (aget k "kid") (aget header "kid"))))
|
||||||
key (if key
|
matching-key (if matching-key
|
||||||
key
|
matching-key
|
||||||
(p/let [keys (get-jwks-keys jwks-url :force? true)
|
(p/let [jwks-keys (get-jwks-keys jwks-url :force? true)
|
||||||
key (.find keys (fn [k] (= (aget k "kid") (aget header "kid"))))]
|
matching-key (.find jwks-keys (fn [k] (= (aget k "kid") (aget header "kid"))))]
|
||||||
key))
|
matching-key))
|
||||||
_ (when-not key (throw (ex-info "kid" {})))
|
_ (when-not matching-key (throw (ex-info "kid" {})))
|
||||||
crypto-key (import-rsa-key key)
|
crypto-key (import-rsa-key matching-key)
|
||||||
data (.encode text-encoder (str header-part "." payload-part))
|
data (.encode text-encoder (str header-part "." payload-part))
|
||||||
signature (base64url->uint8array signature-part)
|
signature (base64url->uint8array signature-part)
|
||||||
ok (.verify js/crypto.subtle
|
ok (.verify js/crypto.subtle
|
||||||
"RSASSA-PKCS1-v1_5"
|
"RSASSA-PKCS1-v1_5"
|
||||||
crypto-key
|
crypto-key
|
||||||
signature
|
signature
|
||||||
data)]
|
data)]
|
||||||
(when ok
|
(when ok
|
||||||
(cache-token! token payload now-ms)
|
(cache-token! token payload now-ms)
|
||||||
payload)))))
|
payload))))))
|
||||||
|
|||||||
18
deps/db-sync/.clj-condo/config.edn
vendored
Normal file
18
deps/db-sync/.clj-condo/config.edn
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{:linters
|
||||||
|
{:aliased-namespace-symbol {:level :warning}
|
||||||
|
:namespace-name-mismatch {:level :warning}
|
||||||
|
:used-underscored-binding {:level :warning}
|
||||||
|
:shadowed-var {:level :warning
|
||||||
|
:exclude [meta name key keys uuid type]}
|
||||||
|
|
||||||
|
:consistent-alias
|
||||||
|
{:aliases {clojure.pprint pprint
|
||||||
|
clojure.string string
|
||||||
|
datascript.core d
|
||||||
|
datascript.transit dt
|
||||||
|
logseq.publish.common publish-common
|
||||||
|
logseq.publish.model publish-model}}}
|
||||||
|
:lint-as {promesa.core/let clojure.core/let
|
||||||
|
shadow.cljs.modern/defclass clj-kondo.lint-as/def-catch-all}
|
||||||
|
:skip-comments true
|
||||||
|
:output {:progress true}}
|
||||||
9
deps/db-sync/src/logseq/db_sync/worker.cljs
vendored
9
deps/db-sync/src/logseq/db_sync/worker.cljs
vendored
@@ -185,10 +185,6 @@
|
|||||||
[^js self ^js ws]
|
[^js self ^js ws]
|
||||||
(swap! (presence* self) dissoc ws))
|
(swap! (presence* self) dissoc ws))
|
||||||
|
|
||||||
(defn- fail-fast [tag data]
|
|
||||||
(log/error tag data)
|
|
||||||
(throw (ex-info (name tag) data)))
|
|
||||||
|
|
||||||
(defn- coerce-http-request [schema-key body]
|
(defn- coerce-http-request [schema-key body]
|
||||||
(if-let [coercer (get db-sync-schema/http-request-coercers schema-key)]
|
(if-let [coercer (get db-sync-schema/http-request-coercers schema-key)]
|
||||||
(let [coerced (coerce coercer body {:schema schema-key :dir :request})]
|
(let [coerced (coerce coercer body {:schema schema-key :dir :request})]
|
||||||
@@ -277,11 +273,6 @@
|
|||||||
(let [url (js/URL. (.-url request))]
|
(let [url (js/URL. (.-url request))]
|
||||||
(str (.-origin url) "/assets/" graph-id "/" snapshot-id ".snapshot")))
|
(str (.-origin url) "/assets/" graph-id "/" snapshot-id ".snapshot")))
|
||||||
|
|
||||||
(defn- maybe-compress-stream [stream]
|
|
||||||
(if (exists? js/CompressionStream)
|
|
||||||
(.pipeThrough stream (js/CompressionStream. "gzip"))
|
|
||||||
stream))
|
|
||||||
|
|
||||||
(defn- maybe-decompress-stream [stream encoding]
|
(defn- maybe-decompress-stream [stream encoding]
|
||||||
(if (and (= encoding snapshot-content-encoding) (exists? js/DecompressionStream))
|
(if (and (= encoding snapshot-content-encoding) (exists? js/DecompressionStream))
|
||||||
(.pipeThrough stream (js/DecompressionStream. "gzip"))
|
(.pipeThrough stream (js/DecompressionStream. "gzip"))
|
||||||
|
|||||||
2
deps/publish/.clj-kondo/config.edn
vendored
2
deps/publish/.clj-kondo/config.edn
vendored
@@ -12,7 +12,7 @@
|
|||||||
datascript.transit dt
|
datascript.transit dt
|
||||||
logseq.publish.common publish-common
|
logseq.publish.common publish-common
|
||||||
logseq.publish.model publish-model}}}
|
logseq.publish.model publish-model}}}
|
||||||
:lint-as {logseq.publish.async/js-await clojure.core/let
|
:lint-as {promesa.core/let clojure.core/let
|
||||||
shadow.cljs.modern/defclass clj-kondo.lint-as/def-catch-all}
|
shadow.cljs.modern/defclass clj-kondo.lint-as/def-catch-all}
|
||||||
:skip-comments true
|
:skip-comments true
|
||||||
:output {:progress true}}
|
:output {:progress true}}
|
||||||
|
|||||||
@@ -110,18 +110,6 @@ $ typos -w
|
|||||||
|
|
||||||
To configure it e.g. for dealing with false positives, see `typos.toml`.
|
To configure it e.g. for dealing with false positives, see `typos.toml`.
|
||||||
|
|
||||||
### Separate DB and File Graph Code
|
|
||||||
|
|
||||||
There is a growing number of code and features that are only for file or DB graphs. Run this linter to
|
|
||||||
ensure that code you add or modify keeps with existing conventions:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ bb lint:db-and-file-graphs-separate
|
|
||||||
✅ All checks passed!
|
|
||||||
```
|
|
||||||
|
|
||||||
The main convention is that file and db specific files go under directories named `file_based` and `db_based` respectively. To see the full list of file and db specific namespaces and files see the top of [the script](/scripts/src/logseq/tasks/dev/db_and_file_graphs.clj).
|
|
||||||
|
|
||||||
### Separate Worker from Frontend
|
### Separate Worker from Frontend
|
||||||
|
|
||||||
The worker and frontend code share common code from deps/ and `frontend.common.*`. However, the worker should never depend on other frontend namespaces as it could pull in libraries like React which cause it to fail hard. Likewise the frontend should never depend on worker namespaces. Run this linter to ensure worker and frontend namespaces don't require each other:
|
The worker and frontend code share common code from deps/ and `frontend.common.*`. However, the worker should never depend on other frontend namespaces as it could pull in libraries like React which cause it to fail hard. Likewise the frontend should never depend on worker namespaces. Run this linter to ensure worker and frontend namespaces don't require each other:
|
||||||
@@ -363,7 +351,7 @@ These tasks are specific to database graphs. For these tasks there is a one time
|
|||||||
$ bb dev:transact test-db '[:find ?b :where [?b :block/title "say wut"]]' '(fn [id] (vector :db/add id :block/title "say woot!"))'
|
$ bb dev:transact test-db '[:find ?b :where [?b :block/title "say wut"]]' '(fn [id] (vector :db/add id :block/title "say woot!"))'
|
||||||
Updated 1 block(s) for graph test-db!
|
Updated 1 block(s) for graph test-db!
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the dev command `Replace graph with its db.sqlite file` to use the updated graph in the desktop app.
|
Run the dev command `Replace graph with its db.sqlite file` to use the updated graph in the desktop app.
|
||||||
|
|
||||||
* `dev:create` - Create a DB graph given a `sqlite.build` EDN file
|
* `dev:create` - Create a DB graph given a `sqlite.build` EDN file
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
"bb lint:carve"
|
"bb lint:carve"
|
||||||
"bb lint:large-vars"
|
"bb lint:large-vars"
|
||||||
"bb lint:worker-and-frontend-separate"
|
"bb lint:worker-and-frontend-separate"
|
||||||
"bb lint:db-and-file-graphs-separate"
|
|
||||||
"bb lang:validate-translations"
|
"bb lang:validate-translations"
|
||||||
"bb lint:ns-docstrings"]]
|
"bb lint:ns-docstrings"]]
|
||||||
(println cmd)
|
(println cmd)
|
||||||
|
|||||||
@@ -1080,6 +1080,61 @@
|
|||||||
(concat (map (fn [id] [:db/retractEntity id]) retract-block-ids))
|
(concat (map (fn [id] [:db/retractEntity id]) retract-block-ids))
|
||||||
keep-last-update)))
|
keep-last-update)))
|
||||||
|
|
||||||
|
(defn- apply-remote-tx-with-local-changes!
|
||||||
|
[{:keys [conn local-txs reversed-tx-data safe-remote-tx-data remote-deleted-blocks
|
||||||
|
temp-tx-meta *remote-tx-report *reversed-tx-report *remote-deleted-ids *rebase-tx-data]}]
|
||||||
|
(let [batch-tx-meta {:rtc-tx? true
|
||||||
|
;; Reverse/rebase batches can temporarily violate block schema.
|
||||||
|
:skip-validate-db? true}]
|
||||||
|
(ldb/transact-with-temp-conn!
|
||||||
|
conn
|
||||||
|
batch-tx-meta
|
||||||
|
(fn [temp-conn _*batch-tx-data]
|
||||||
|
(let [tx-meta temp-tx-meta
|
||||||
|
reversed-tx-report (ldb/transact! temp-conn reversed-tx-data (assoc tx-meta :op :reverse))
|
||||||
|
_ (reset! *reversed-tx-report reversed-tx-report)
|
||||||
|
;; 2. transact remote tx-data
|
||||||
|
remote-tx-report (let [tx-meta (assoc tx-meta :op :transact-remote-tx-data)]
|
||||||
|
(ldb/transact! temp-conn safe-remote-tx-data tx-meta))
|
||||||
|
_ (reset! *remote-tx-report remote-tx-report)
|
||||||
|
local-deleted-blocks (get-local-deleted-blocks reversed-tx-report reversed-tx-data)
|
||||||
|
_ (when (seq remote-deleted-blocks)
|
||||||
|
(reset! *remote-deleted-ids (set (map :block/uuid remote-deleted-blocks))))
|
||||||
|
deleted-nodes (concat local-deleted-blocks remote-deleted-blocks)
|
||||||
|
deleted-ids (set (keep :block/uuid deleted-nodes))
|
||||||
|
;; 3. rebase pending local txs
|
||||||
|
rebase-tx-report (when (seq local-txs)
|
||||||
|
(let [pending-tx-data (mapcat :tx local-txs)
|
||||||
|
rebased-tx-data (sanitize-tx-data
|
||||||
|
(or (:db-after remote-tx-report)
|
||||||
|
(:db-after reversed-tx-report))
|
||||||
|
pending-tx-data
|
||||||
|
(set (map :block/uuid local-deleted-blocks)))]
|
||||||
|
(when (seq rebased-tx-data)
|
||||||
|
(ldb/transact! temp-conn rebased-tx-data (assoc tx-meta :op :rebase)))))
|
||||||
|
;; 4. delete nodes and fix tx data
|
||||||
|
db @temp-conn
|
||||||
|
deleted-nodes (keep (fn [id] (d/entity db [:block/uuid id])) deleted-ids)]
|
||||||
|
(delete-nodes! temp-conn deleted-nodes (assoc tx-meta :op :delete-blocks))
|
||||||
|
(fix-tx! temp-conn remote-tx-report rebase-tx-report (assoc tx-meta :op :fix))))
|
||||||
|
{:listen-db (fn [{:keys [tx-meta tx-data]}]
|
||||||
|
(when-not (contains? #{:reverse :transact-remote-tx-data} (:op tx-meta))
|
||||||
|
(swap! *rebase-tx-data into tx-data)))})))
|
||||||
|
|
||||||
|
(defn- apply-remote-tx-without-local-changes!
|
||||||
|
[{:keys [conn safe-remote-tx-data remote-deleted-block-ids temp-tx-meta]}]
|
||||||
|
(let [db @conn]
|
||||||
|
(ldb/transact-with-temp-conn!
|
||||||
|
conn
|
||||||
|
{:rtc-tx? true}
|
||||||
|
(fn [temp-conn]
|
||||||
|
(when (seq safe-remote-tx-data)
|
||||||
|
(d/transact! temp-conn safe-remote-tx-data {:rtc-tx? true}))
|
||||||
|
(when-let [deleted-nodes (keep (fn [id] (d/entity db [:block/uuid id]))
|
||||||
|
remote-deleted-block-ids)]
|
||||||
|
(delete-nodes! temp-conn deleted-nodes
|
||||||
|
(assoc temp-tx-meta :op :delete-blocks)))))))
|
||||||
|
|
||||||
(defn- apply-remote-tx!
|
(defn- apply-remote-tx!
|
||||||
[repo client tx-data*]
|
[repo client tx-data*]
|
||||||
(if-let [conn (worker-state/get-datascript-conn repo)]
|
(if-let [conn (worker-state/get-datascript-conn repo)]
|
||||||
@@ -1108,57 +1163,20 @@
|
|||||||
:temp-conn? true
|
:temp-conn? true
|
||||||
:gen-undo-ops? false
|
:gen-undo-ops? false
|
||||||
:persist-op? false}
|
:persist-op? false}
|
||||||
tx-report
|
apply-context {:conn conn
|
||||||
(if has-local-changes?
|
:local-txs local-txs
|
||||||
(let [batch-tx-meta {:rtc-tx? true}]
|
:reversed-tx-data reversed-tx-data
|
||||||
(ldb/transact-with-temp-conn!
|
:safe-remote-tx-data safe-remote-tx-data
|
||||||
conn
|
:remote-deleted-blocks remote-deleted-blocks
|
||||||
batch-tx-meta
|
:remote-deleted-block-ids remote-deleted-block-ids
|
||||||
(fn [temp-conn _*batch-tx-data]
|
:temp-tx-meta temp-tx-meta
|
||||||
(let [tx-meta temp-tx-meta
|
:*remote-tx-report *remote-tx-report
|
||||||
reversed-tx-report (ldb/transact! temp-conn reversed-tx-data (assoc tx-meta :op :reverse))
|
:*reversed-tx-report *reversed-tx-report
|
||||||
_ (reset! *reversed-tx-report reversed-tx-report)
|
:*remote-deleted-ids *remote-deleted-ids
|
||||||
;; 2. transact remote tx-data
|
:*rebase-tx-data *rebase-tx-data}
|
||||||
remote-tx-report (let [tx-meta (assoc tx-meta :op :transact-remote-tx-data)]
|
tx-report (if has-local-changes?
|
||||||
(ldb/transact! temp-conn safe-remote-tx-data tx-meta))
|
(apply-remote-tx-with-local-changes! apply-context)
|
||||||
_ (reset! *remote-tx-report remote-tx-report)
|
(apply-remote-tx-without-local-changes! apply-context))
|
||||||
local-deleted-blocks (get-local-deleted-blocks reversed-tx-report reversed-tx-data)
|
|
||||||
_ (when (seq remote-deleted-blocks)
|
|
||||||
(reset! *remote-deleted-ids (set (map :block/uuid remote-deleted-blocks))))
|
|
||||||
;; _ (prn :debug
|
|
||||||
;; :local-deleted-blocks (map (fn [b] (select-keys b [:db/id :block/title])) local-deleted-blocks)
|
|
||||||
;; :remote-deleted-blocks remote-deleted-blocks)
|
|
||||||
deleted-nodes (concat local-deleted-blocks remote-deleted-blocks)
|
|
||||||
deleted-ids (set (keep :block/uuid deleted-nodes))
|
|
||||||
;; 3. rebase pending local txs
|
|
||||||
rebase-tx-report (when (seq local-txs)
|
|
||||||
(let [pending-tx-data (mapcat :tx local-txs)
|
|
||||||
rebased-tx-data (sanitize-tx-data
|
|
||||||
(or (:db-after remote-tx-report)
|
|
||||||
(:db-after reversed-tx-report))
|
|
||||||
pending-tx-data
|
|
||||||
(set (map :block/uuid local-deleted-blocks)))]
|
|
||||||
;; (prn :debug :pending-tx-data pending-tx-data)
|
|
||||||
;; (prn :debug :rebased-tx-data rebased-tx-data)
|
|
||||||
(when (seq rebased-tx-data)
|
|
||||||
(ldb/transact! temp-conn rebased-tx-data (assoc tx-meta :op :rebase)))))
|
|
||||||
;; 4. delete nodes and fix tx data
|
|
||||||
db @temp-conn
|
|
||||||
deleted-nodes (keep (fn [id] (d/entity db [:block/uuid id])) deleted-ids)]
|
|
||||||
(delete-nodes! temp-conn deleted-nodes (assoc tx-meta :op :delete-blocks))
|
|
||||||
(fix-tx! temp-conn remote-tx-report rebase-tx-report (assoc tx-meta :op :fix))))
|
|
||||||
{:listen-db (fn [{:keys [tx-meta tx-data]}]
|
|
||||||
(when-not (contains? #{:reverse :transact-remote-tx-data} (:op tx-meta))
|
|
||||||
(swap! *rebase-tx-data into tx-data)))}))
|
|
||||||
(ldb/transact-with-temp-conn!
|
|
||||||
conn
|
|
||||||
{:rtc-tx? true}
|
|
||||||
(fn [temp-conn]
|
|
||||||
(when (seq safe-remote-tx-data)
|
|
||||||
(d/transact! temp-conn safe-remote-tx-data {:rtc-tx? true}))
|
|
||||||
(when-let [deleted-nodes (keep (fn [id] (d/entity db [:block/uuid id])) remote-deleted-block-ids)]
|
|
||||||
(delete-nodes! temp-conn deleted-nodes
|
|
||||||
(assoc temp-tx-meta :op :delete-blocks))))))
|
|
||||||
remote-tx-report @*remote-tx-report]
|
remote-tx-report @*remote-tx-report]
|
||||||
;; persist rebase tx to client ops
|
;; persist rebase tx to client ops
|
||||||
(when has-local-changes?
|
(when has-local-changes?
|
||||||
|
|||||||
@@ -423,6 +423,38 @@
|
|||||||
(str "db empty seed=" seed " history=" (count @history))))))))))
|
(str "db empty seed=" seed " history=" (count @history))))))))))
|
||||||
|
|
||||||
(defonce op-runs 500)
|
(defonce op-runs 500)
|
||||||
|
|
||||||
|
(defn- run-random-ops!
|
||||||
|
[rng server clients repo->state base-uuid history run-ops-opts steps]
|
||||||
|
(dotimes [_ steps]
|
||||||
|
(let [client (rand-nth! rng clients)
|
||||||
|
state (get repo->state (:repo client))]
|
||||||
|
(run-ops! rng (assoc client :base-uuid base-uuid :state state) 1 history run-ops-opts)
|
||||||
|
(sync-loop! server clients))))
|
||||||
|
|
||||||
|
(defn- run-local-ops!
|
||||||
|
[rng conn base-uuid state history run-ops-opts steps]
|
||||||
|
(dotimes [_ steps]
|
||||||
|
(run-ops! rng {:conn conn :base-uuid base-uuid :state state} 1 history run-ops-opts)))
|
||||||
|
|
||||||
|
(defn- assert-synced-attrs!
|
||||||
|
[seed history attrs-a attrs-b attrs-c]
|
||||||
|
(when-not (= attrs-a attrs-b)
|
||||||
|
(let [[a b] (take 2 (data/diff attrs-a attrs-b))]
|
||||||
|
(prn :debug :diff :attrs-a a :attrs-b b)))
|
||||||
|
(when-not (= attrs-a attrs-c)
|
||||||
|
(let [[a c] (take 2 (data/diff attrs-a attrs-c))]
|
||||||
|
(prn :debug :diff :attrs-a a :attrs-c c)))
|
||||||
|
(is (= attrs-a attrs-b)
|
||||||
|
(str "db mismatch A/B seed=" seed
|
||||||
|
" a=" (count attrs-a)
|
||||||
|
" b=" (count attrs-b)
|
||||||
|
" history=" (count @history)))
|
||||||
|
(is (= attrs-a attrs-c)
|
||||||
|
(str "db mismatch A/C seed=" seed
|
||||||
|
" a=" (count attrs-a)
|
||||||
|
" c=" (count attrs-c)
|
||||||
|
" history=" (count @history))))
|
||||||
(deftest three-clients-single-repo-sim-test
|
(deftest three-clients-single-repo-sim-test
|
||||||
(prn :debug "run three-clients-single-repo-sim-test")
|
(prn :debug "run three-clients-single-repo-sim-test")
|
||||||
(testing "db-sync convergence with three clients sharing one repo"
|
(testing "db-sync convergence with three clients sharing one repo"
|
||||||
@@ -451,12 +483,10 @@
|
|||||||
repo-c {:conn conn-c :ops-conn ops-c}}
|
repo-c {:conn conn-c :ops-conn ops-c}}
|
||||||
(fn []
|
(fn []
|
||||||
(reset! db-sync/*repo->latest-remote-tx {})
|
(reset! db-sync/*repo->latest-remote-tx {})
|
||||||
(ensure-base-page! conn-a base-uuid)
|
(doseq [conn [conn-a conn-b conn-c]]
|
||||||
(ensure-base-page! conn-b base-uuid)
|
(ensure-base-page! conn base-uuid))
|
||||||
(ensure-base-page! conn-c base-uuid)
|
(doseq [repo [repo-a repo-b repo-c]]
|
||||||
(client-op/update-local-tx repo-a 0)
|
(client-op/update-local-tx repo 0))
|
||||||
(client-op/update-local-tx repo-b 0)
|
|
||||||
(client-op/update-local-tx repo-c 0)
|
|
||||||
(let [clients [{:repo repo-a :conn conn-a :client client-a :online? true}
|
(let [clients [{:repo repo-a :conn conn-a :client client-a :online? true}
|
||||||
{:repo repo-b :conn conn-b :client client-b :online? true}
|
{:repo repo-b :conn conn-b :client client-b :online? true}
|
||||||
{:repo repo-c :conn conn-c :client client-c :online? true}]
|
{:repo repo-c :conn conn-c :client client-c :online? true}]
|
||||||
@@ -464,24 +494,16 @@
|
|||||||
run-ops-opts {}]
|
run-ops-opts {}]
|
||||||
(prn :debug :phase-a)
|
(prn :debug :phase-a)
|
||||||
;; Phase A: all online
|
;; Phase A: all online
|
||||||
(dotimes [_ op-runs]
|
(run-random-ops! rng server clients repo->state base-uuid history run-ops-opts op-runs)
|
||||||
(let [client (rand-nth! rng clients)
|
|
||||||
state (get repo->state (:repo client))]
|
|
||||||
(run-ops! rng (assoc client :base-uuid base-uuid :state state) 1 history run-ops-opts)
|
|
||||||
(sync-loop! server clients)))
|
|
||||||
|
|
||||||
;; Phase B: C offline, A/B online
|
;; Phase B: C offline, A/B online
|
||||||
(prn :debug :phase-b-c-offline)
|
(prn :debug :phase-b-c-offline)
|
||||||
(let [clients-phase-b [{:repo repo-a :conn conn-a :client client-a :online? true}
|
(let [clients-phase-b [{:repo repo-a :conn conn-a :client client-a :online? true}
|
||||||
{:repo repo-b :conn conn-b :client client-b :online? true}
|
{:repo repo-b :conn conn-b :client client-b :online? true}
|
||||||
{:repo repo-c :conn conn-c :client client-c :online? false}]]
|
{:repo repo-c :conn conn-c :client client-c :online? false}]]
|
||||||
(dotimes [_ op-runs]
|
(run-random-ops! rng server (subvec (vec clients-phase-b) 0 2) repo->state
|
||||||
(let [client (rand-nth! rng (subvec (vec clients-phase-b) 0 2))
|
base-uuid history run-ops-opts op-runs)
|
||||||
state (get repo->state (:repo client))]
|
(run-local-ops! rng conn-c base-uuid state-c history run-ops-opts op-runs))
|
||||||
(run-ops! rng (assoc client :base-uuid base-uuid :state state) 1 history run-ops-opts)
|
|
||||||
(sync-loop! server clients-phase-b)))
|
|
||||||
(dotimes [_ op-runs]
|
|
||||||
(run-ops! rng {:client client-c :conn conn-c :base-uuid base-uuid :state state-c} 1 history run-ops-opts)))
|
|
||||||
|
|
||||||
;; Phase C: reconnect C
|
;; Phase C: reconnect C
|
||||||
(prn :debug :phase-c-reconnect)
|
(prn :debug :phase-c-reconnect)
|
||||||
@@ -492,13 +514,9 @@
|
|||||||
(let [clients-phase-d [{:repo repo-a :conn conn-a :client client-a :online? false}
|
(let [clients-phase-d [{:repo repo-a :conn conn-a :client client-a :online? false}
|
||||||
{:repo repo-b :conn conn-b :client client-b :online? true}
|
{:repo repo-b :conn conn-b :client client-b :online? true}
|
||||||
{:repo repo-c :conn conn-c :client client-c :online? true}]]
|
{:repo repo-c :conn conn-c :client client-c :online? true}]]
|
||||||
(dotimes [_ op-runs]
|
(run-random-ops! rng server (subvec (vec clients-phase-d) 1 3) repo->state
|
||||||
(let [client (rand-nth! rng (subvec (vec clients-phase-d) 1 3))
|
base-uuid history run-ops-opts op-runs)
|
||||||
state (get repo->state (:repo client))]
|
(run-local-ops! rng conn-a base-uuid state-a history run-ops-opts op-runs))
|
||||||
(run-ops! rng (assoc client :base-uuid base-uuid :state state) 1 history run-ops-opts)
|
|
||||||
(sync-loop! server clients-phase-d)))
|
|
||||||
(dotimes [_ op-runs]
|
|
||||||
(run-ops! rng {:conn conn-a :base-uuid base-uuid :state state-a} 1 history run-ops-opts)))
|
|
||||||
|
|
||||||
;; Final sync
|
;; Final sync
|
||||||
(prn :debug :final-sync)
|
(prn :debug :final-sync)
|
||||||
@@ -514,21 +532,4 @@
|
|||||||
(let [attrs-a (block-attr-map @conn-a)
|
(let [attrs-a (block-attr-map @conn-a)
|
||||||
attrs-b (block-attr-map @conn-b)
|
attrs-b (block-attr-map @conn-b)
|
||||||
attrs-c (block-attr-map @conn-c)]
|
attrs-c (block-attr-map @conn-c)]
|
||||||
(when-not (= attrs-a attrs-b)
|
(assert-synced-attrs! seed history attrs-a attrs-b attrs-c))))))))
|
||||||
(let [[a b] (take 2 (data/diff attrs-a attrs-b))]
|
|
||||||
(prn :debug :diff :attrs-a a
|
|
||||||
:attrs-b b)))
|
|
||||||
(when-not (= attrs-a attrs-c)
|
|
||||||
(let [[a c] (take 2 (data/diff attrs-a attrs-c))]
|
|
||||||
(prn :debug :diff :attrs-a a
|
|
||||||
:attrs-c c)))
|
|
||||||
(is (= attrs-a attrs-b)
|
|
||||||
(str "db mismatch A/B seed=" seed
|
|
||||||
" a=" (count attrs-a)
|
|
||||||
" b=" (count attrs-b)
|
|
||||||
" history=" (count @history)))
|
|
||||||
(is (= attrs-a attrs-c)
|
|
||||||
(str "db mismatch A/C seed=" seed
|
|
||||||
" a=" (count attrs-a)
|
|
||||||
" c=" (count attrs-c)
|
|
||||||
" history=" (count @history))))))))))
|
|
||||||
|
|||||||
Reference in New Issue
Block a user