Skip to content

Instantly share code, notes, and snippets.

@rgm
Created July 31, 2019 16:10
Show Gist options
  • Save rgm/1b44f546c9ff7cccaeddb7b73d4a4291 to your computer and use it in GitHub Desktop.
Save rgm/1b44f546c9ff7cccaeddb7b73d4a4291 to your computer and use it in GitHub Desktop.

Revisions

  1. rgm revised this gist Jul 31, 2019. No changes.
  2. rgm created this gist Jul 31, 2019.
    55 changes: 55 additions & 0 deletions re_frame_subscription_graph.cljs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    (ns rgm.re-frame-subscription-graph
    "Generate a graphviz .dot from re-frame subscriptions.
    Sometimes the signal graph can get hard to grok. These two fns hijack
    re-frame's subscription registration to harvest these inter-sub dependencies
    as data, at which point we can produce .dot syntax and rely on graphviz
    (or .dot-compatible tools like Omnigraffle) for quick-and-dirty visualization.
    Usage:
    - refer `subscribe` and `reg-sub` into subscription-registering
    namespaces. (This is trivial if you've required re-frame as
    `(:require [re-frame.core :refer [subscribe reg-sub])`).
    - let figwheel (or whatever) eval the subs namespaces
    - Use a repl-connected editor to eval `(print-graphviz-source)`. Harvest the
    output and feed into graphviz."
    (:require [re-frame.core]))

    (defn subscribe
    "Drop-in hack to just get the query id when called in the initial signals fn
    of an L3 subscription. Leave as seq to make it easier to flatten/set later."
    [query]
    (take 1 query))

    (def *edges (atom []))

    (defn reg-sub
    "Build up a seq of directed this-sub-relies-on-that edges in *edges as
    code eval sets up all subscription handlers. Drop this into namespaces
    where you want to build up a graph, in lieu of `re-frame.core/reg-sub`."
    [query-id & args]
    (case (count args)
    ; 1 (println (str "L2-" query-id)) ;; must be an L2
    2 (let [signals-fn (first args) ;; must be an L3
    signals (set (flatten (signals-fn)))]
    (doseq [s signals]
    (swap! *edges conj [s query-id])
    #_(println (str s " -> " query-id))))
    nil)
    ;; have already broken everything about the app here; not sure this is all
    ;; that useful to pass through the reg-sub
    (apply re-frame.core/reg-sub query-id args))

    (defn print-graphviz-source
    []
    (println "digraph G {")
    (doseq [[origin dest] @*edges]
    (println " \"" origin "\" -> \"" dest "\""))
    (println "}"))

    (comment

    (reset! *edges [])
    (print-graphviz-source)

    )