Collect layer 2/3 information when subs run
We can then use it for determining subscription layer level when subs are created or destroyed.
This commit is contained in:
parent
b87a584589
commit
b62ed52847
|
@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. This change
|
||||||
|
|
||||||
* External windows not loading
|
* External windows not loading
|
||||||
* All app-db and subscription path expansions are now independent of each other [#134](https://github.com/Day8/re-frame-trace/issues/134).
|
* All app-db and subscription path expansions are now independent of each other [#134](https://github.com/Day8/re-frame-trace/issues/134).
|
||||||
|
* Layer 2/3 calculations are more accurate now. We now use the last seen layer level when a subscription runs, to inform it's layer level if it was created or destroyed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,59 @@
|
||||||
|
This document briefly explains why `re-frame-trace` gives you an option to
|
||||||
This document briefly explains why `re-frame-trace` gives you an option to
|
ignore unchanged layer 2 subscriptions.
|
||||||
ignore unchanged layer 2 subscriptions.
|
|
||||||
|
|
||||||
### Background
|
### Background
|
||||||
|
|
||||||
The `re-frame` docs
|
The `re-frame` docs
|
||||||
[make a distinction](https://github.com/Day8/re-frame/blob/master/docs/SubscriptionInfographic.md)
|
[make a distinction](https://github.com/Day8/re-frame/blob/master/docs/SubscriptionInfographic.md)
|
||||||
between `layer 2` and `layer 3` subscriptions:
|
between `layer 2` and `layer 3` subscriptions:
|
||||||
- `layer 2` subscriptions extract data directly from `app-db` and should be
|
- `layer 2` subscriptions extract data directly from `app-db` and should be
|
||||||
trivial in nature. There should be no computation in them beyond
|
trivial in nature. There should be no computation in them beyond
|
||||||
what is necessary to extract a value from `app-db`
|
what is necessary to extract a value from `app-db`
|
||||||
- `layer 3` subscriptions take values from `layer 2` nodes as inputs, and
|
- `layer 3` subscriptions take values from `layer 2` nodes as inputs, and
|
||||||
compute a materialised view of those values. Just to repeat: they never directly
|
compute a materialised view of those values. Just to repeat: they never directly
|
||||||
extract values from `app-db`. They create new values where necessary, and because of it
|
extract values from `app-db`. They create new values where necessary, and because of it
|
||||||
they to do more serious CPU work. So we never want to run a
|
they to do more serious CPU work. So we never want to run a
|
||||||
`layer 3` subscriptions unless it is necessary.
|
`layer 3` subscriptions unless it is necessary.
|
||||||
|
|
||||||
This structure delivers efficiency. You see, **all** (currently instantiated) `layer 2` subscriptions
|
This structure delivers efficiency. You see, **all** (currently instantiated) `layer 2` subscriptions
|
||||||
will run **every** time `app-db` changes in any way. All of them. Every time.
|
will run **every** time `app-db` changes in any way. All of them. Every time.
|
||||||
And `app-db` changes on almost every event, so we want them to be computationally
|
And `app-db` changes on almost every event, so we want them to be computationally
|
||||||
trivial.
|
trivial.
|
||||||
|
|
||||||
If the value of a `layer 2` subscription tests `=` to its previous value, then the further
|
If the value of a `layer 2` subscription tests `=` to its previous value, then the further
|
||||||
propagation of values through the signal graph will be pruned.
|
propagation of values through the signal graph will be pruned.
|
||||||
The more computationally intensive `layer 3` subscriptions, and ultimately
|
The more computationally intensive `layer 3` subscriptions, and ultimately
|
||||||
the views, will only recompute if and when there has been a change in their data inputs.
|
the views, will only recompute if and when there has been a change in their data inputs.
|
||||||
|
|
||||||
We don't want your app recomputing views only to find that nothing has changed. Inefficient.
|
We don't want your app recomputing views only to find that nothing has changed. Inefficient.
|
||||||
|
|
||||||
### Back To Tracing
|
### Back To Tracing
|
||||||
|
|
||||||
Because `layer 2` subs run on every single modification of `app-db`, and because
|
Because `layer 2` subs run on every single modification of `app-db`, and because
|
||||||
very often nothing has changed, their trace can be a bit noisy. Yes, it happened,
|
very often nothing has changed, their trace can be a bit noisy. Yes, it happened,
|
||||||
but it just isn't that interesting.
|
but it just isn't that interesting.
|
||||||
|
|
||||||
So `re-frame-trace` gives you the option of filtering out trace for
|
So `re-frame-trace` gives you the option of filtering out trace for
|
||||||
the `layer 2` subscriptions where the value "this time" is the same as the
|
the `layer 2` subscriptions where the value "this time" is the same as the
|
||||||
value "last time".
|
value "last time".
|
||||||
|
|
||||||
On the other hand, if a `layer 2` subscription runs and its value is
|
On the other hand, if a `layer 2` subscription runs and its value is
|
||||||
different to last time, that's potentially fascinating and you'll want to
|
different to last time, that's potentially fascinating and you'll want to
|
||||||
be told all about it. :-)
|
be told all about it. :-)
|
||||||
|
|
||||||
|
### Why do I sometimes see "Layer ?" when viewing a subscription?
|
||||||
|
|
||||||
|
To determine whether a subscription is a layer 2 or layer 3, re-frame-trace
|
||||||
|
looks at the input signals to a subscription. If one of the input signals is
|
||||||
|
app-db then the subscription is a layer 2 sub, otherwise it is a layer 3. If
|
||||||
|
a subscription hasn't run yet, then we can't know if it is a layer 2 or 3.
|
||||||
|
|
||||||
|
In almost all cases, a subscription will be created (by `(subscribe [:my-sub])`)
|
||||||
|
and run (by dereferencing the subscription) within the same epoch, providing
|
||||||
|
the layer level. If you see "Layer ?" this means that a subscription was created
|
||||||
|
but not used. This may indicate a bug in your application, although there are
|
||||||
|
cases where this is ok.
|
||||||
|
|
||||||
|
In most cases, after a few more epochs, that subscription will have run, and we
|
||||||
|
know it's layer level, and can use it for any subscriptions shown on any future
|
||||||
|
(and past) epochs.
|
||||||
|
|
|
@ -510,10 +510,26 @@
|
||||||
(contains? events-to-ignore (first event)))) new-matches)
|
(contains? events-to-ignore (first event)))) new-matches)
|
||||||
all-matches (reduce conj previous-matches new-matches)
|
all-matches (reduce conj previous-matches new-matches)
|
||||||
retained-matches (into [] (take-last number-of-epochs-to-retain all-matches))
|
retained-matches (into [] (take-last number-of-epochs-to-retain all-matches))
|
||||||
|
app-db-id (get-in db [:app-db :reagent-id])
|
||||||
|
subscription-info (->> new-traces
|
||||||
|
(filter metam/subscription-re-run?)
|
||||||
|
(reduce (fn [state trace]
|
||||||
|
;; TODO: can we take any shortcuts by assuming that a sub with
|
||||||
|
;; multiple input signals is a layer 3? I don't *think* so because
|
||||||
|
;; one of those input signals could be a naughty subscription to app-db
|
||||||
|
;; directly.
|
||||||
|
;; If any of the input signals are app-db, it is a layer 2 sub, else 3
|
||||||
|
(assoc-in state
|
||||||
|
[(:operation trace) :layer]
|
||||||
|
(if (some #(= app-db-id %) (get-in trace [:tags :input-signals]))
|
||||||
|
2
|
||||||
|
3)))
|
||||||
|
(get-in db [:epochs :subscription-info] {})))
|
||||||
first-id-to-retain (:id (ffirst retained-matches))
|
first-id-to-retain (:id (ffirst retained-matches))
|
||||||
retained-traces (into [] (comp (drop-while #(< (:id %) first-id-to-retain))
|
retained-traces (into [] (comp (drop-while #(< (:id %) first-id-to-retain))
|
||||||
(remove (fn [trace] (or (when drop-reagent (metam/low-level-reagent-trace? trace))
|
(remove (fn [trace]
|
||||||
(when drop-re-frame (metam/low-level-re-frame-trace? trace)))))) all-traces)]
|
(or (when drop-reagent (metam/low-level-reagent-trace? trace))
|
||||||
|
(when drop-re-frame (metam/low-level-re-frame-trace? trace)))))) all-traces)]
|
||||||
(-> db
|
(-> db
|
||||||
(assoc-in [:traces :all-traces] retained-traces)
|
(assoc-in [:traces :all-traces] retained-traces)
|
||||||
(update :epochs (fn [epochs]
|
(update :epochs (fn [epochs]
|
||||||
|
@ -521,7 +537,8 @@
|
||||||
:matches retained-matches
|
:matches retained-matches
|
||||||
:matches-by-id (into {} (map (juxt first-match-id identity)) retained-matches)
|
:matches-by-id (into {} (map (juxt first-match-id identity)) retained-matches)
|
||||||
:match-ids (mapv first-match-id retained-matches)
|
:match-ids (mapv first-match-id retained-matches)
|
||||||
:parse-state parse-state)))))
|
:parse-state parse-state
|
||||||
|
:subscription-info subscription-info)))))
|
||||||
;; Else
|
;; Else
|
||||||
db)))
|
db)))
|
||||||
|
|
||||||
|
|
|
@ -351,6 +351,12 @@
|
||||||
(fn [traces]
|
(fn [traces]
|
||||||
(filter metam/subscription? traces)))
|
(filter metam/subscription? traces)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:subs/subscription-info
|
||||||
|
:<- [:epochs/epoch-root]
|
||||||
|
(fn [epoch]
|
||||||
|
(:subscription-info epoch)))
|
||||||
|
|
||||||
(defn sub-sort-val
|
(defn sub-sort-val
|
||||||
[sub]
|
[sub]
|
||||||
(case (:type sub)
|
(case (:type sub)
|
||||||
|
@ -375,7 +381,8 @@
|
||||||
:subs/all-subs
|
:subs/all-subs
|
||||||
:<- [:subs/all-sub-traces]
|
:<- [:subs/all-sub-traces]
|
||||||
:<- [:app-db/reagent-id]
|
:<- [:app-db/reagent-id]
|
||||||
(fn [[traces app-db-id]]
|
:<- [:subs/subscription-info]
|
||||||
|
(fn [[traces app-db-id sub-info]]
|
||||||
(let [raw (map (fn [trace] (let [pod-type (sub-op-type->type trace)
|
(let [raw (map (fn [trace] (let [pod-type (sub-op-type->type trace)
|
||||||
path-data (get-in trace [:tags :query-v])
|
path-data (get-in trace [:tags :query-v])
|
||||||
;; TODO: detect layer 2/3 for sub/create and sub/destroy
|
;; TODO: detect layer 2/3 for sub/create and sub/destroy
|
||||||
|
@ -385,7 +392,7 @@
|
||||||
3)]
|
3)]
|
||||||
{:id (str pod-type (get-in trace [:tags :reaction]))
|
{:id (str pod-type (get-in trace [:tags :reaction]))
|
||||||
:type pod-type
|
:type pod-type
|
||||||
:layer layer
|
:layer (get-in sub-info [(:operation trace) :layer])
|
||||||
:path-data path-data
|
:path-data path-data
|
||||||
:path (pr-str path-data)
|
:path (pr-str path-data)
|
||||||
:value (get-in trace [:tags :value])
|
:value (get-in trace [:tags :value])
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
:model path
|
:model path
|
||||||
:disabled? true]]]
|
:disabled? true]]]
|
||||||
[rc/gap-f :size common/gs-12s]
|
[rc/gap-f :size common/gs-12s]
|
||||||
[rc/label :label (str "Layer " layer)]
|
[rc/label :label (str "Layer " (if (some? layer) layer "?"))]
|
||||||
|
|
||||||
;; TODO: capture previous sub run value and allow diffing it.
|
;; TODO: capture previous sub run value and allow diffing it.
|
||||||
#_[rc/gap-f :size common/gs-12s]
|
#_[rc/gap-f :size common/gs-12s]
|
||||||
|
|
Loading…
Reference in New Issue