Add Fase 0 telemetry for the server-client migration baseline
Adds dev-only counters, with no behavior change, to answer the open
questions from the migration plan before touching the transport:
- frontend.state/get-invoke-stats: per-thread-api-method count/total-ms/
max-ms for every <invoke-db-worker call, to census how many invokes a
typical navigation generates and their latency distribution.
- db-worker-node: per-repo in-flight /v1/invoke counter that logs a new
concurrency high-water mark, to check whether concurrent client writes
actually overlap before deciding on a write queue.
- subs-loader/get-stats: dedup-hit vs new-entry counts for load!, and
batch-size distribution per slot kind at flush, to check whether
in-flight snapshot requests are already deduplicated and whether the
{:children 25 :resources 25} limits are worth raising for network RTT.
Verified with clojure -M:cljs compile app and compile db-worker-node
(0 warnings on both).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,22 @@
|
||||
|
||||
(defonce ^:private *batch (atom {}))
|
||||
|
||||
(defonce ^:private *stats (atom {:dedup-hits 0 :new-entries 0 :flushes 0 :batch-sizes {}}))
|
||||
|
||||
(defn get-stats
|
||||
"Snapshot of subs-loader batching counters: :dedup-hits counts load! calls
|
||||
that reused an already-pending slot request within the same unflushed
|
||||
batch window (see `load!`); :batch-sizes tallies entries per slot kind
|
||||
across flushes. Dev-only instrumentation for the server-client migration
|
||||
latency baseline (see docs/agent-guide); does not affect batching or the
|
||||
`limits` above."
|
||||
[]
|
||||
@*stats)
|
||||
|
||||
(defn reset-stats!
|
||||
[]
|
||||
(reset! *stats {:dedup-hits 0 :new-entries 0 :flushes 0 :batch-sizes {}}))
|
||||
|
||||
(defn- reject!
|
||||
[entries error]
|
||||
(doseq [{:keys [result]} entries]
|
||||
@@ -45,6 +61,13 @@
|
||||
[]
|
||||
(when @state/db-worker-ready?
|
||||
(let [batch (take-batch!)]
|
||||
(swap! *stats
|
||||
(fn [s]
|
||||
(-> s
|
||||
(update :flushes inc)
|
||||
(update :batch-sizes
|
||||
#(merge-with + %
|
||||
(frequencies (map (comp slot-kind first :slot-key) batch)))))))
|
||||
(doseq [[graph-id graph-entries] (group-by :graph-id batch)
|
||||
entries (request-groups graph-entries)]
|
||||
(-> (state/<invoke-db-worker :thread-api/get-render-snapshots
|
||||
@@ -72,9 +95,11 @@
|
||||
[graph-id slot-key schedule!]
|
||||
(let [entry-key [graph-id slot-key]]
|
||||
(if-let [result (get-in @*batch [entry-key :result])]
|
||||
result
|
||||
(do (swap! *stats update :dedup-hits inc)
|
||||
result)
|
||||
(let [result (p/deferred)
|
||||
schedule? (empty? @*batch)]
|
||||
(swap! *stats update :new-entries inc)
|
||||
(swap! *batch assoc entry-key
|
||||
{:graph-id graph-id :slot-key slot-key :result result})
|
||||
(when schedule?
|
||||
|
||||
@@ -63,6 +63,28 @@
|
||||
(reset! ready? (fn? worker))))
|
||||
ready?))
|
||||
|
||||
(defonce ^:private *invoke-stats (atom {}))
|
||||
|
||||
(defn get-invoke-stats
|
||||
"Snapshot of db-worker invoke counters, keyed by thread-api method kw. Each
|
||||
entry is {:count N :total-ms N :max-ms N}. Dev-only instrumentation for the
|
||||
server-client migration latency baseline (see docs/agent-guide); does not
|
||||
affect invocation behavior."
|
||||
[]
|
||||
@*invoke-stats)
|
||||
|
||||
(defn reset-invoke-stats!
|
||||
[]
|
||||
(reset! *invoke-stats {}))
|
||||
|
||||
(defn- record-invoke-stat!
|
||||
[qkw elapsed-ms]
|
||||
(swap! *invoke-stats update qkw
|
||||
(fn [{:keys [count total-ms max-ms] :or {count 0 total-ms 0 max-ms 0}}]
|
||||
{:count (inc count)
|
||||
:total-ms (+ total-ms elapsed-ms)
|
||||
:max-ms (max max-ms elapsed-ms)})))
|
||||
|
||||
(defn <invoke-db-worker
|
||||
"invoke db-worker thread api"
|
||||
[qkw & args]
|
||||
@@ -70,11 +92,13 @@
|
||||
(when (nil? worker)
|
||||
(prn :<invoke-db-worker-error qkw)
|
||||
(throw (ex-info "db-worker has not been initialized" {})))
|
||||
(p/let [result (apply worker qkw args)]
|
||||
(if (or (instance? ExceptionInfo result)
|
||||
(instance? js/Error result))
|
||||
(p/rejected result)
|
||||
result))))
|
||||
(let [started-at (js/performance.now)]
|
||||
(-> (p/let [result (apply worker qkw args)]
|
||||
(if (or (instance? ExceptionInfo result)
|
||||
(instance? js/Error result))
|
||||
(p/rejected result)
|
||||
result))
|
||||
(p/finally (fn [] (record-invoke-stat! qkw (- (js/performance.now) started-at))))))))
|
||||
|
||||
(def ^:private export-block-text-indent-styles #{"dashes" "spaces" "no-indent"})
|
||||
|
||||
|
||||
@@ -20,6 +20,25 @@
|
||||
(defonce ^:private *sse-clients (atom #{}))
|
||||
(defonce ^:private *lock-info (atom nil))
|
||||
(defonce ^:private *server-list-file (atom nil))
|
||||
(defonce ^:private *inflight-by-repo (atom {}))
|
||||
(defonce ^:private *max-inflight-by-repo (atom {}))
|
||||
|
||||
(defn- invoke-started!
|
||||
"Increments the /v1/invoke in-flight counter for repo and logs a new
|
||||
concurrency high-water mark when observed. Dev-only instrumentation for the
|
||||
server-client migration multi-client baseline (see docs/agent-guide); has no
|
||||
effect on request handling."
|
||||
[repo]
|
||||
(let [n (get (swap! *inflight-by-repo update repo (fnil inc 0)) repo)
|
||||
prev-max (get @*max-inflight-by-repo repo 0)]
|
||||
(when (> n prev-max)
|
||||
(swap! *max-inflight-by-repo assoc repo n)
|
||||
(log/info :db-worker-node-invoke-concurrency-high-water-mark
|
||||
{:repo repo :concurrent n}))))
|
||||
|
||||
(defn- invoke-finished!
|
||||
[repo]
|
||||
(swap! *inflight-by-repo update repo (fnil dec 0)))
|
||||
|
||||
(defn- server-list-file-path
|
||||
[root-dir]
|
||||
@@ -376,7 +395,9 @@
|
||||
(p/let [_ (when-not (contains? non-repo-methods method-kw)
|
||||
(let [{:keys [path lock]} @*lock-info]
|
||||
(db-lock/assert-lock-owner! path lock)))
|
||||
result (<invoke! proxy method-str method-kw args')]
|
||||
_ (invoke-started! bound-repo)
|
||||
result (-> (<invoke! proxy method-str method-kw args')
|
||||
(p/finally (fn [] (invoke-finished! bound-repo))))]
|
||||
(send-json! res 200 {:ok true :resultTransit result}))))
|
||||
(p/catch (fn [error]
|
||||
(log-invoke-error! res error method-kw)))))
|
||||
|
||||
Reference in New Issue
Block a user