Improve sub parsing

This commit is contained in:
Daniel Compton 2018-02-09 01:12:59 +13:00
parent 9d90992470
commit 3f94b3c960
4 changed files with 108 additions and 141 deletions

View File

@ -536,7 +536,7 @@
;; like its reagent id, when it was created, run, disposed, what values it returned, e.t.c.
subscription-info (metam/subscription-info (get-in db [:epochs :subscription-info] {}) filtered-traces (get-in db [:app-db :reagent-id]))
sub-state (get-in db [:epochs :sub-state] metam/initial-sub-state)
subscription-match-state (utils/spy "SUB" (metam/subscription-match-state sub-state filtered-traces new-matches))
subscription-match-state (metam/subscription-match-state sub-state filtered-traces new-matches)
subscription-matches (rest subscription-match-state)
new-sub-state (last subscription-match-state)
timing (mapv (fn [match]

View File

@ -208,6 +208,7 @@
(def initial-sub-state
{:last-matched-id 0
:pre-epoch-state {}
:reaction-state {}})
(defn parse-traces [parse-state traces]
@ -284,11 +285,14 @@
[state]
(into {}
(comp
;; Remove disposed subscriptions
(filter (fn [me] (when-not (:disposed? (val me)) me)))
;; Remove transient state
(map (fn [[k v]]
[k (dissoc v :order :created? :run? :disposed? :previous-value)])))
state))
(defn process-sub-traces
[initial-state traces]
(reduce (fn [state trace]
@ -327,6 +331,9 @@
;; traces are going to be changing because of app-db changes.
;; We collect and present the state for both phases for consumption in the subs panel
;; If you look closely at the state of the subscriptions, and the traces they derive from, you will
;; come to a disturbing realisation: Disposed reactions are resurrected and continue to be run.
;; This is tracked in https://github.com/reagent-project/reagent/pull/270.
;#?(:cljs (js/console.log "New matches?" (not (empty? new-matches))))
(reductions (fn [state match]
@ -344,30 +351,17 @@
(id-between-xf first-match-id last-match-id)
(filter subscription?))
filtered-traces)
reset-rx-state (reset-sub-state (:reaction-state state))]
(-> (->> epoch-traces
(reduce (fn [state trace]
(let [tags (get trace :tags)
reaction-id (:reaction tags)]
(case (:op-type trace)
:sub/create (assoc state reaction-id {:created? true
:subscription (:query-v tags)
:order [:sub/create]})
:sub/run (update state reaction-id (fn [sub-state]
(-> (if (contains? sub-state :value)
(assoc sub-state :previous-value (:value sub-state))
sub-state)
(assoc :run? true
:value (:value tags))
(update :order (fnil conj []) :sub/run))))
:sub/dispose (-> (assoc-in state [reaction-id :disposed?] true)
(update-in [reaction-id :order] (fnil conj []) :sub/dispose))
(do #?(:cljs (js/console.warn "Unhandled sub trace, this is a bug, report to re-frame-trace please" trace))
state))))
reset-rx-state)
(assoc state :reaction-state))
(assoc :first-matched-id first-match-id
:last-matched-id last-match-id
:previous-matched-id previous-id))))
reaction-state (:reaction-state state)
pre-epoch-state (-> reaction-state
(reset-sub-state)
(process-sub-traces pre-epoch-traces))
epoch-state (-> pre-epoch-state
(reset-sub-state)
(process-sub-traces epoch-traces))]
{:pre-epoch-state pre-epoch-state
:reaction-state epoch-state
:first-matched-id first-match-id
:last-matched-id last-match-id
:previous-matched-id previous-id}))
sub-state
new-matches))

View File

@ -397,7 +397,7 @@
(s/def :sub/id string!)
(s/def :sub/reagent-id string!)
(s/def :sub/type #{:created :re-run :destroyed :not-run})
(s/def :sub/layer pos-int?)
(s/def :sub/layer (s/nilable pos-int?))
(s/def :sub/path-data any?)
(s/def :sub/path string!)
(s/def :sub/value any?)
@ -408,25 +408,11 @@
(s/def :subs/view-subs (s/coll-of :subs/view-panel-sub))
(rf/reg-sub
:subs/inter-epoch-subs
(fn [db]
(let [sub
[{:id ":test1"
:reagent-id "ra87"
:type :created
:layer 3
:path-data [:test/sub]
:path (pr-str [:test/sub])
:value 5
:previous-value 3}]]
(when-not (s/valid? :subs/view-subs sub)
(js/console.error (expound/expound-str :subs/view-subs sub)))
sub)))
(defn sub-sort-val
[sub]
(case (:type sub)
[sub-type]
(case sub-type
:created 1
:re-run 2
:destroyed 3
@ -444,66 +430,49 @@
:not-run))
(defn prepare-pod-info
"Returns sub info prepared for rendering in pods"
[[sub-info sub-state]]
(let [rx-state (:reaction-state sub-state)
subx (->>
rx-state
(remove (fn [me] (nil? (:order (val me)))))
(map (fn [me] (let [state (val me)
subscription (:subscription state)
sub {:id (key me)
:reagent-id (key me)
:type :created
:layer (get-in sub-info [(first subscription) :layer])
:path-data subscription
:path (pr-str subscription)
:order (:order state)}
sub (if (contains? state :value)
(assoc sub :value (:value state))
sub)
sub (if (contains? state :previous-value)
(assoc sub :previous-value (:previous-value state))
sub)]
sub))))
]
(utils/spy "subx" subx)
(when-not (s/valid? :subs/view-subs subx)
(js/console.error (expound/expound-str :subs/view-subs subx)))
subx))
(rf/reg-sub
:subs/all-subs
:<- [:subs/all-sub-traces]
:<- [:app-db/reagent-id]
:subs/inter-epoch-subs
:<- [:subs/subscription-info]
:<- [:subs/current-epoch-sub-state]
(fn [[traces app-db-id sub-info sub-state]]
(let [rx-state (:reaction-state sub-state)
raw (map (fn [trace]
(let [pod-type (sub-op-type->type trace)
path-data (get-in trace [:tags :query-v])
reagent-id (get-in trace [:tags :reaction])
sub (-> {:id (str pod-type reagent-id)
:reagent-id reagent-id
:type pod-type
:layer (get-in sub-info [(:operation trace) :layer])
:path-data path-data
:path (pr-str path-data)
;; TODO: Get not run subscriptions
})
sub (if (contains? (:tags trace) :value)
(assoc sub :value (get-in trace [:tags :value]))
sub)
sub (if (contains? (get rx-state reagent-id) :previous-value)
(assoc sub :previous-value (get-in rx-state [reagent-id :previous-value]))
sub)]
sub))
traces)
re-run (->> raw
(filter #(= :re-run (:type %)))
(map (juxt :path-data identity))
(into {}))
created (->> raw
(filter #(= :created (:type %)))
(map (juxt :path-data identity))
(into {}))
raw (keep (fn [sub]
(case (:type sub)
:created (if-some [re-run-sub (get re-run (:path-data sub))]
(assoc sub :value (:value re-run-sub))
sub)
prepare-pod-info)
:re-run (when-not (contains? created (:path-data sub))
sub)
sub))
raw)
;; Filter out run if it was created
;; Group together run time
run-multiple? (into {}
(filter (fn [[k v]] (< 1 v)))
(frequencies (map :id raw)))
output (map (fn [sub] (assoc sub :run-times (get run-multiple? (:id sub)))) raw)
subs (sort-by identity subscription-comparator output)]
(when-not (s/valid? :subs/view-subs subs)
(js/console.error (expound/expound-str :subs/view-subs subs)))
subs
)))
(rf/reg-sub
:subs/all-subs
:<- [:subs/subscription-info]
:<- [:subs/current-epoch-sub-state]
prepare-pod-info)
(rf/reg-sub
:subs/visible-subs

View File

@ -20,25 +20,26 @@
(defn sub-tag-class [type]
(case type
:created "rft-tag__subscription_created"
:destroyed "rft-tag__subscription_destroyed"
:re-run "rft-tag__subscription_re_run"
:not-run "rft-tag__subscription_not_run"
:sub/create "rft-tag__subscription_created"
:sub/dispose "rft-tag__subscription_destroyed"
:sub/run "rft-tag__subscription_re_run"
:sub/not-run "rft-tag__subscription_not_run"
""))
(def tag-types {:created {:long "CREATED" :short "CREATED"}
:destroyed {:long "DESTROYED" :short "DESTROY"}
:re-run {:long "RE-RUN" :short "RE-RUN"}
:not-run {:long "NOT-RUN" :short "NOT-RUN"}})
(def tag-types {:sub/create {:long "CREATED" :short "C"}
:sub/dispose {:long "DISPOSED" :short "D"}
:sub/run {:long "RUN" :short "R"}
:sub/not-run {:long "NOT-RUN" :short "N"}
nil {:long "NIL" :short "NIL"}})
(def *finished-animation? (r/atom false))
(def animation-duration 150)
(defn long-tag-desc [type]
(get-in tag-types [type :long] "???"))
(get-in tag-types [type :long] (str type)))
(defn short-tag-desc [type]
(get-in tag-types [type :short] "???"))
(get-in tag-types [type :short] (str type)))
(defn sub-tag [type label]
[components/tag (sub-tag-class type) label])
@ -75,10 +76,10 @@
:font-size "18px"
:font-weight "lighter"}}
"Summary:"]
[title-tag :created (long-tag-desc :created) @created-count]
[title-tag :re-run (long-tag-desc :re-run) @re-run-count]
[title-tag :destroyed (long-tag-desc :destroyed) @destroyed-count]
[title-tag :not-run (long-tag-desc :not-run) @not-run-count]]]
[title-tag :sub/create (long-tag-desc :sub/create) @created-count]
[title-tag :sub/run (long-tag-desc :sub/run) @re-run-count]
[title-tag :sub/dispose (long-tag-desc :sub/dispose) @destroyed-count]
[title-tag :sub/not-run (long-tag-desc :sub/not-run) @not-run-count]]]
[rc/h-box
:align :center
:gap common/gs-19s
@ -95,7 +96,7 @@
:style {:margin-top "6px"}
:on-change #(rf/dispatch [:subs/ignore-unchanged-l2-subs? %])]]]]]))
(defn pod-header [{:keys [id type layer path open? diff? run-times]}]
(defn pod-header [{:keys [id layer path open? diff? run-times order]}]
[rc/h-box
:class (str "app-db-path--header " (when-not open? "rounded-bottom"))
:align :center
@ -110,9 +111,13 @@
:child [rc/box
:margin "auto"
:child [:span.arrow (if open? "▼" "▶")]]]
[rc/box
:width "64px" ;; (100-36)px from box above
:child [sub-tag type (short-tag-desc type)]]
[rc/h-box
:children (into [] (map (fn [o] [sub-tag o (short-tag-desc o)])) order)]
#_[rc/box
;:width "64px" ;; (100-36)px from box above
:child [sub-tag (first order) (short-tag-desc (first order))]]
;; TODO: report if a sub was run multiple times
#_(when run-times
[:span "Warning: run " run-times " times"])
@ -145,7 +150,7 @@
:margin "0px 3px"}}]]
[rc/gap-f :size common/gs-12s]]])
(defn pod [{:keys [id type layer path open? diff?] :as pod-info}]
(defn pod [{:keys [id layer path open? diff?] :as pod-info}]
(let [render-diff? (and open? diff?)
value? (contains? pod-info :value)
previous-value? (contains? pod-info :previous-value)]
@ -162,8 +167,8 @@
(when open?
(let [main-value (:value pod-info)
#_(cond value? (:value pod-info)
previous-value? (:previous-value pod-info)
:else nil)]
previous-value? (:previous-value pod-info)
:else nil)]
[rc/v-box
:class (str "data-viewer" (when-not diff? " rounded-bottom"))
:style {:margin (css-join pod-padding pod-padding "0px" pod-padding)
@ -181,9 +186,8 @@
:duration animation-duration})
(when render-diff?
(let [diffable? (and value? previous-value?)
[diff-before diff-after _] (when render-diff?
(clojure.data/diff (:previous-value pod-info)
(:value pod-info)))]
[diff-before diff-after _] (clojure.data/diff (:previous-value pod-info)
(:value pod-info))]
[rc/v-box
:children [[rc/v-box
:class "app-db-path--link"
@ -235,12 +239,12 @@
:children [[rc/label :label "There are no subscriptions to show"]]])
(defn pod-section []
(let [visible-subs @(rf/subscribe [:subs/visible-subs])
(let [visible-subs @(rf/subscribe [:subs/visible-subs])
inter-epoch-subs @(rf/subscribe [:subs/inter-epoch-subs])
sub-expansions @(rf/subscribe [:subs/sub-expansions])
all-subs (if @(rf/subscribe [:settings/debug?])
(cons {:path [:subs/current-epoch-sub-state] :id "debug" :value @(rf/subscribe [:subs/current-epoch-sub-state])} visible-subs)
visible-subs)]
sub-expansions @(rf/subscribe [:subs/sub-expansions])
all-subs (if @(rf/subscribe [:settings/debug?])
(cons {:path [:subs/current-epoch-sub-state] :id "debug" :value @(rf/subscribe [:subs/current-epoch-sub-state])} visible-subs)
visible-subs)]
[rc/v-box
;:size "1"
;:gap pod-gap
@ -259,13 +263,13 @@
^{:key (:id p)}
[pod (merge p (get sub-expansions (:id p)))])
#_[animated/component
(animated/v-box-options {:on-finish #(reset! *finished-animation? true)
:duration animation-duration
:style {:flex "1 1 0px"
:overflow-x "hidden"
:overflow-y "auto"}})
(animated/v-box-options {:on-finish #(reset! *finished-animation? true)
:duration animation-duration
:style {:flex "1 1 0px"
:overflow-x "hidden"
:overflow-y "auto"}})
]
]
[rc/line :size "5px"
:style {:margin "19px 0px"}]
[:h2 {:class "bm-heading-text"
@ -275,13 +279,13 @@
[pod (merge p (get sub-expansions (:id p)))])
#_[animated/component
(animated/v-box-options {:on-finish #(reset! *finished-animation? true)
:duration animation-duration
:style {:flex "1 1 0px"
:overflow-x "hidden"
:overflow-y "auto"}})
(animated/v-box-options {:on-finish #(reset! *finished-animation? true)
:duration animation-duration
:style {:flex "1 1 0px"
:overflow-x "hidden"
:overflow-y "auto"}})
]
]
]
]))