enhance: sync startup latency

1. Removes startup dependency on remote-graphs fetch for initial sync start.
2. Removes unnecessary restart churn.
3. Shaves trigger scheduling delay.
This commit is contained in:
Tienson Qin
2026-02-26 12:12:54 +08:00
parent a1cbcf8aaa
commit 560ce3ca4f
5 changed files with 82 additions and 18 deletions

View File

@@ -153,4 +153,4 @@ conditions:
(apply c.m/mix)
(m/latest vector flows/current-login-user-flow)
(m/eduction (keep (fn [[current-user trigger-event]] (when current-user trigger-event))))
(c.m/debounce 200)))
(c.m/debounce 50)))

View File

@@ -185,6 +185,23 @@
[repo]
(some #(= repo (:url %)) (state/get-rtc-graphs)))
(defn- graph-has-local-rtc-id?
[repo]
(boolean (some-> (db/get-db repo)
ldb/get-graph-rtc-uuid)))
(defn- remote-graphs-unknown?
[]
(not= false (:rtc/loading-graphs? @state/state)))
(defn- should-start-rtc?
[repo]
(or (graph-in-remote-list? repo)
;; During startup, remote graph list might not be fetched yet.
;; If local DB already has graph UUID, start optimistically to reduce cold-start latency.
(and (remote-graphs-unknown?)
(graph-has-local-rtc-id? repo))))
(defn- normalize-graph-e2ee?
[graph-e2ee?]
(if (nil? graph-e2ee?)
@@ -193,12 +210,14 @@
(defn <rtc-start!
[repo & {:keys [_stop-before-start?] :as _opts}]
(if (graph-in-remote-list? repo)
(if (should-start-rtc? repo)
(do
(log/info :db-sync/start {:repo repo})
(state/<invoke-db-worker :thread-api/db-sync-start repo))
(do
(log/info :db-sync/skip-start {:repo repo :reason :graph-not-in-remote-list})
(log/info :db-sync/skip-start {:repo repo :reason :graph-not-in-remote-list
:remote-graphs-loading? (:rtc/loading-graphs? @state/state)
:has-local-rtc-id? (graph-has-local-rtc-id? repo)})
(p/resolved nil))))
(defn <rtc-stop!

View File

@@ -37,6 +37,13 @@
(js->clj :keywordize-keys true)
(update :cognito:username decode-username)))
(defn- parse-jwt-safe
[jwt]
(try
(parse-jwt jwt)
(catch :default _
nil)))
(defn- expired? [parsed-jwt]
(some->
(* 1000 (:exp parsed-jwt))
@@ -191,12 +198,34 @@
"Refresh id-token&access-token, pull latest repos, returns nil when tokens are not available."
[]
(println "restore-tokens-from-localstorage")
(let [refresh-token (js/localStorage.getItem "refresh-token")]
(when refresh-token
(let [refresh-token (js/localStorage.getItem "refresh-token")
id-token (js/localStorage.getItem "id-token")
access-token (js/localStorage.getItem "access-token")
restored-from-cache?
(boolean
(when (and (string? refresh-token) (not (string/blank? refresh-token))
(string? id-token) (not (string/blank? id-token))
(string? access-token) (not (string/blank? access-token)))
(when-let [parsed (parse-jwt-safe id-token)]
(when-not (expired? parsed)
(set-tokens! id-token access-token refresh-token)
true))))
should-refresh?
(and (string? refresh-token)
(not (string/blank? refresh-token))
(or (not restored-from-cache?)
(some-> (state/get-auth-id-token)
parse-jwt-safe
almost-expired?)))]
(when restored-from-cache?
;; Publish login event immediately so sync can start without waiting token refresh request.
(state/pub-event! [:user/fetch-info-and-graphs]))
(when should-refresh?
(go
(<! (<refresh-id-token&access-token))
;; refresh remote graph list by pub login event
(when (user-uuid) (state/pub-event! [:user/fetch-info-and-graphs]))))))
;; If tokens were not restored from cache, this is the first chance to continue login flow.
(when (and (not restored-from-cache?) (user-uuid))
(state/pub-event! [:user/fetch-info-and-graphs]))))))
(defn login-callback
[session]

View File

@@ -1311,22 +1311,40 @@
(reset! worker-state/*db-sync-client nil))
(p/resolved nil))
(defn- active-client-for?
[client repo graph-id]
(when (and client (= repo (:repo client)) (= graph-id (:graph-id client)))
(let [ws (:ws client)
ws-state (some-> (:ws-state client) deref)
ws-ready-state (when ws (ready-state ws))]
(or (= :open ws-state)
(contains? #{0 1} ws-ready-state)))))
(defn start!
[repo]
(p/do!
(stop!)
(let [base (ws-base-url)
graph-id (get-graph-id repo)]
(if (and (string? base) (seq base) (seq graph-id))
(let [base (ws-base-url)
graph-id (get-graph-id repo)
current @worker-state/*db-sync-client]
(cond
(not (and (string? base) (seq base) (seq graph-id)))
(do
(log/info :db-sync/start-skipped {:repo repo :graph-id graph-id :base base})
(p/resolved nil))
(active-client-for? current repo graph-id)
(do
(broadcast-rtc-state! current)
(p/resolved nil))
:else
(p/do!
(stop!)
(let [client (ensure-client-state! repo)
url (format-ws-url base graph-id)
_ (ensure-client-graph-uuid! repo graph-id)
connected (assoc client :graph-id graph-id)
connected (connect! repo connected url)]
(reset! worker-state/*db-sync-client connected)
(p/resolved nil))
(do
(log/info :db-sync/start-skipped {:repo repo :graph-id graph-id :base base})
(p/resolved nil))))))
(defn enqueue-local-tx!

View File

@@ -152,7 +152,7 @@
(reset! native-top-bar-listener? true)))
(defn- configure-native-top-bar!
[repo {:keys [tab title route-name route-view sync-color favorited? show-sync?]}]
[{:keys [tab title route-name route-view sync-color favorited? show-sync?]}]
(when (and (mobile-util/native-platform?)
mobile-util/native-top-bar)
(let [hidden? (and (mobile-util/native-ios?) (= tab "search"))
@@ -247,7 +247,6 @@
title (or (:block/title block) fallback-title)
f (fn [favorited?]
(configure-native-top-bar!
current-repo
{:tab tab
:title title
:route-name route-name
@@ -277,7 +276,6 @@
title (:block/title block)
f (fn [favorited?]
(configure-native-top-bar!
current-repo
{:tab tab
:title title
:route-name route-name